@aman_asmuei/amem 0.9.1 → 0.9.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 +347 -267
- package/dist/dashboard.js +217 -4
- package/dist/dashboard.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,10 +26,11 @@
|
|
|
26
26
|
</p>
|
|
27
27
|
|
|
28
28
|
<p align="center">
|
|
29
|
-
<a href="#-
|
|
29
|
+
<a href="#-getting-started">Getting Started</a> •
|
|
30
|
+
<a href="#-how-it-works">How It Works</a> •
|
|
30
31
|
<a href="#-features">Features</a> •
|
|
31
|
-
<a href="
|
|
32
|
-
<a href="#-usage-
|
|
32
|
+
<a href="#%EF%B8%8F-tools-reference">Tools</a> •
|
|
33
|
+
<a href="#-usage-guide">Usage Guide</a> •
|
|
33
34
|
<a href="#-architecture">Architecture</a> •
|
|
34
35
|
<a href="#-contributing">Contributing</a>
|
|
35
36
|
</p>
|
|
@@ -45,14 +46,12 @@ Every time you start a new conversation with an AI coding assistant, it starts f
|
|
|
45
46
|
> *"We chose PostgreSQL over MongoDB"* — doesn't remember why.
|
|
46
47
|
>
|
|
47
48
|
> *"I prefer early returns and pnpm"* — explained again. And again.
|
|
48
|
-
>
|
|
49
|
-
> A critical decision from **last week**? Gone.
|
|
50
49
|
|
|
51
50
|
**You repeat yourself. Every. Single. Session.**
|
|
52
51
|
|
|
53
52
|
## The Solution
|
|
54
53
|
|
|
55
|
-
**amem** plugs into any MCP-compatible AI tool and gives it persistent, searchable, lossless memory.
|
|
54
|
+
**amem** plugs into any MCP-compatible AI tool and gives it persistent, searchable, lossless memory — with temporal validity, privacy controls, and a knowledge graph.
|
|
56
55
|
|
|
57
56
|
```
|
|
58
57
|
You: "Don't use any type in TypeScript"
|
|
@@ -65,26 +64,35 @@ No cloud. No API keys. Everything stays on your machine.
|
|
|
65
64
|
|
|
66
65
|
---
|
|
67
66
|
|
|
68
|
-
##
|
|
67
|
+
## Getting Started
|
|
69
68
|
|
|
70
|
-
### 1
|
|
69
|
+
### Step 1: Install
|
|
71
70
|
|
|
72
71
|
```bash
|
|
73
72
|
npm install -g @aman_asmuei/amem
|
|
74
73
|
```
|
|
75
74
|
|
|
76
|
-
### 2
|
|
75
|
+
### Step 2: Auto-Configure
|
|
77
76
|
|
|
78
77
|
```bash
|
|
79
|
-
amem-cli init
|
|
80
|
-
amem-cli rules
|
|
78
|
+
amem-cli init # Detects & configures Claude Code, Cursor, Windsurf, GitHub Copilot
|
|
79
|
+
amem-cli rules # Generates extraction rules so your AI uses amem proactively
|
|
80
|
+
amem-cli hooks # Installs automatic memory capture (PostToolUse + SessionEnd)
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
<details>
|
|
84
|
-
<summary><strong>
|
|
84
|
+
<summary><strong>What does each command do?</strong></summary>
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
| Command | What it does |
|
|
87
|
+
|---|---|
|
|
88
|
+
| `amem-cli init` | Finds your installed AI tools and adds amem to their MCP server config. Works with Claude Code (`~/.claude/settings.json`), Cursor (`~/.cursor/mcp.json`), Windsurf (`~/.windsurf/mcp.json`), and GitHub Copilot. |
|
|
89
|
+
| `amem-cli rules` | Writes a set of memory extraction guidelines to your tool's rules file (e.g., `CLAUDE.md`, `.cursorrules`). This teaches the AI *when* and *how* to store memories. |
|
|
90
|
+
| `amem-cli hooks` | Installs Claude Code lifecycle hooks that passively capture tool observations (PostToolUse) and auto-summarize sessions on exit (Stop). Memories accumulate without you asking. |
|
|
91
|
+
|
|
92
|
+
</details>
|
|
93
|
+
|
|
94
|
+
<details>
|
|
95
|
+
<summary><strong>Or configure manually (Claude Code)</strong></summary>
|
|
88
96
|
|
|
89
97
|
```bash
|
|
90
98
|
claude mcp add amem -- npx -y @aman_asmuei/amem
|
|
@@ -106,7 +114,7 @@ Or add to `~/.claude/settings.json`:
|
|
|
106
114
|
</details>
|
|
107
115
|
|
|
108
116
|
<details>
|
|
109
|
-
<summary><strong>Cursor / Windsurf / Other MCP Clients</strong></summary>
|
|
117
|
+
<summary><strong>Or configure manually (Cursor / Windsurf / Other MCP Clients)</strong></summary>
|
|
110
118
|
|
|
111
119
|
```json
|
|
112
120
|
{
|
|
@@ -118,115 +126,143 @@ Or add to `~/.claude/settings.json`:
|
|
|
118
126
|
|
|
119
127
|
</details>
|
|
120
128
|
|
|
121
|
-
|
|
129
|
+
### Step 3: Restart Your AI Tool
|
|
130
|
+
|
|
131
|
+
You'll see **28 tools**, **6 resources**, and **2 prompts** ready to go.
|
|
132
|
+
|
|
133
|
+
### Step 4: Verify
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
amem-cli stats # Should show "0 memories" initially
|
|
137
|
+
amem-cli dashboard # Opens web dashboard at localhost:3333
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Then start a conversation and tell your AI:
|
|
122
141
|
|
|
123
|
-
|
|
142
|
+
> *"Remember: always use strict TypeScript, never use any type"*
|
|
124
143
|
|
|
125
|
-
|
|
144
|
+
Start a **new** conversation and ask:
|
|
145
|
+
|
|
146
|
+
> *"What do you remember about TypeScript?"*
|
|
147
|
+
|
|
148
|
+
It should recall the correction instantly.
|
|
126
149
|
|
|
127
150
|
---
|
|
128
151
|
|
|
129
|
-
##
|
|
152
|
+
## How It Works
|
|
130
153
|
|
|
131
|
-
|
|
154
|
+
amem captures knowledge in **three ways** — you choose how hands-on you want to be:
|
|
132
155
|
|
|
133
|
-
|
|
134
|
-
|---|---|---|
|
|
135
|
-
| **NEW** | Temporal validity | Memories have `valid_from`/`valid_until` — facts expire, old decisions are preserved for history |
|
|
136
|
-
| **NEW** | Auto-expire contradictions | Storing a new memory auto-expires conflicting old ones (Zep-style temporal knowledge graph) |
|
|
137
|
-
| **NEW** | `memory_expire` | Mark a memory as no longer valid — preserved for "what was true when?" queries |
|
|
138
|
-
| **NEW** | Multi-strategy retrieval | `memory_multi_recall` — combines semantic + FTS5 + knowledge graph traversal + temporal recency |
|
|
139
|
-
| **NEW** | Memory tiers | `memory_tier` — core (always injected), working (session-scoped), archival (searchable) |
|
|
140
|
-
| **NEW** | Privacy tags | `<private>...</private>` blocks stripped before storage; auto-redaction of API keys/secrets |
|
|
141
|
-
| **NEW** | Automatic capture | `amem hooks` — installs Claude Code lifecycle hooks (PostToolUse, Stop) for passive observation |
|
|
142
|
-
| **NEW** | Session summaries | `memory_summarize` + `memory_history` — structured session digests with key decisions/corrections |
|
|
143
|
-
| **NEW** | Config system | `~/.amem/config.json` — retrieval weights, privacy rules, tier budgets, hook settings |
|
|
144
|
-
| **NEW** | Dashboard v2 | Tier filter, expired badges, temporal validity display, session summaries section |
|
|
145
|
-
| **PERF** | Configurable scale | `maxCandidates` configurable up to 50K (was hardcoded 5K) |
|
|
156
|
+
### 1. Automatic (zero effort)
|
|
146
157
|
|
|
147
|
-
|
|
158
|
+
With hooks installed (`amem-cli hooks`), amem passively:
|
|
159
|
+
- Logs significant tool calls via the **PostToolUse** hook
|
|
160
|
+
- Auto-summarizes sessions on exit via the **Stop** hook
|
|
161
|
+
- Extracts decisions, corrections, and patterns from conversation flow
|
|
148
162
|
|
|
149
|
-
|
|
150
|
-
|---|---|---|
|
|
151
|
-
| **NEW** | `amem init` | Auto-detect and configure Claude Code, Cursor, Windsurf, GitHub Copilot in one command |
|
|
152
|
-
| **NEW** | `amem rules` | Generate auto-extraction rules so your AI uses amem proactively (CLAUDE.md, .cursorrules, etc.) |
|
|
153
|
-
| **NEW** | `amem dashboard` | Beautiful dark-themed web dashboard — memory list, knowledge graph, stats, reminders, log |
|
|
163
|
+
### 2. Proactive (AI-driven)
|
|
154
164
|
|
|
155
|
-
|
|
156
|
-
|
|
165
|
+
With rules installed (`amem-cli rules`), your AI will:
|
|
166
|
+
- Call `memory_inject` at session start to load corrections & decisions
|
|
167
|
+
- Call `memory_extract` every ~10 exchanges to batch-save insights
|
|
168
|
+
- Call `memory_store` when you correct it or make a decision
|
|
169
|
+
- Call `reminder_check` to surface overdue reminders
|
|
157
170
|
|
|
158
|
-
###
|
|
171
|
+
### 3. Manual (you decide)
|
|
159
172
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
| **NEW** | Embedding cache | LRU cache (128 entries) avoids recomputing identical query embeddings |
|
|
166
|
-
| **NEW** | Content-hash dedup | Exact duplicates caught even without embeddings (SHA-256 prefix) |
|
|
167
|
-
| **FIX** | FTS5 sync | Delete/update triggers use explicit rowid — no more stale FTS index after delete or patch |
|
|
168
|
-
| **FIX** | Multi-process safe | `busy_timeout=5000` — Claude Code + Cursor can share the same DB |
|
|
169
|
-
| **PERF** | Scale protections | Consolidation caps at 500/group, stats uses SQL aggregation |
|
|
170
|
-
|
|
171
|
-
### v0.5.1
|
|
172
|
-
|
|
173
|
-
| | Feature | Description |
|
|
174
|
-
|---|---|---|
|
|
175
|
-
| **NEW** | Progressive disclosure | `memory_recall` with `compact=true` returns ~50-100 token index (~10x savings) |
|
|
176
|
-
| **NEW** | On-demand detail | `memory_detail` retrieves full content by ID (supports partial 8-char match) |
|
|
173
|
+
You can always tell your AI directly:
|
|
174
|
+
- *"Store this as a correction: never mock the database in integration tests"*
|
|
175
|
+
- *"What do you remember about our auth architecture?"*
|
|
176
|
+
- *"Forget the memory about Redis — we switched to Memcached"*
|
|
177
|
+
- *"Promote that correction to core tier so it's always loaded"*
|
|
177
178
|
|
|
178
|
-
|
|
179
|
+
---
|
|
179
180
|
|
|
180
|
-
|
|
181
|
-
|---|---|---|
|
|
182
|
-
| **NEW** | Reminders system | `reminder_set` / `reminder_list` / `reminder_check` / `reminder_complete` — persistent cross-session reminders |
|
|
181
|
+
## Memory Types
|
|
183
182
|
|
|
184
|
-
|
|
183
|
+
Memories are scored and prioritized automatically:
|
|
184
|
+
|
|
185
|
+
| Priority | Type | When to use | Example |
|
|
186
|
+
|:---:|---|---|---|
|
|
187
|
+
| `1.0` | **correction** | User corrects the AI | *"Don't mock the DB in integration tests"* |
|
|
188
|
+
| `0.85` | **decision** | Architecture/design choice made | *"Chose Postgres over Mongo for ACID"* |
|
|
189
|
+
| `0.7` | **pattern** | Recurring coding style | *"Prefers early returns over nesting"* |
|
|
190
|
+
| `0.7` | **preference** | Tool or workflow choice | *"Uses pnpm, not npm"* |
|
|
191
|
+
| `0.5` | **topology** | Codebase structure | *"Auth module lives in src/auth/"* |
|
|
192
|
+
| `0.4` | **fact** | General project knowledge | *"API launched January 2025"* |
|
|
193
|
+
|
|
194
|
+
> **Corrections always surface first.** They are your AI's hard constraints — the things it must never get wrong again.
|
|
185
195
|
|
|
186
|
-
|
|
196
|
+
### Memory Tiers
|
|
197
|
+
|
|
198
|
+
Memories live in one of three tiers:
|
|
199
|
+
|
|
200
|
+
| Tier | Behavior | Use for |
|
|
187
201
|
|---|---|---|
|
|
188
|
-
| **
|
|
189
|
-
| **
|
|
190
|
-
| **
|
|
191
|
-
| **NEW** | Knowledge graph | `memory_relate` — typed bidirectional relations between memories |
|
|
192
|
-
| **NEW** | Temporal queries | `memory_since` — natural language time ranges (`7d`, `2w`, `1h`) |
|
|
193
|
-
| **NEW** | Full-text search | `memory_search` — FTS5 exact match, auto-synced on every write |
|
|
202
|
+
| **Core** | Always injected at session start (~500 tokens max) | Your most critical corrections and decisions |
|
|
203
|
+
| **Working** | Session-scoped, auto-surfaced for current task | Context relevant to what you're doing now |
|
|
204
|
+
| **Archival** | Searchable but not auto-injected (default) | Everything else — the long-term store |
|
|
194
205
|
|
|
195
|
-
###
|
|
206
|
+
### Temporal Validity
|
|
196
207
|
|
|
197
|
-
|
|
198
|
-
-
|
|
208
|
+
Memories aren't forever. When facts change:
|
|
209
|
+
- Old memories get **expired** (not deleted) — preserved for *"what was true in March?"*
|
|
210
|
+
- Contradictions are **auto-detected** — storing a new decision auto-expires the conflicting old one
|
|
211
|
+
- You can query any point in time with `memory_since`
|
|
199
212
|
|
|
200
|
-
|
|
213
|
+
---
|
|
201
214
|
|
|
202
|
-
|
|
203
|
-
- `memory_inject` for proactive context surfacing
|
|
215
|
+
## Features
|
|
204
216
|
|
|
205
|
-
### v0.
|
|
217
|
+
### v0.9.x — The Temporal Intelligence Release
|
|
206
218
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
-
|
|
219
|
+
| Feature | Description |
|
|
220
|
+
|---|---|
|
|
221
|
+
| Temporal validity | Memories have `valid_from`/`valid_until` — facts expire, history preserved |
|
|
222
|
+
| Auto-expire | Storing a new memory auto-expires conflicting old ones |
|
|
223
|
+
| Multi-strategy retrieval | Combines semantic + FTS5 + knowledge graph + temporal recency |
|
|
224
|
+
| Cross-encoder reranking | Optional 2nd-pass reranking for highest accuracy |
|
|
225
|
+
| Memory tiers | Core (always loaded) / Working (session) / Archival (searchable) |
|
|
226
|
+
| Privacy tags | `<private>...</private>` stripped; API keys auto-redacted |
|
|
227
|
+
| Automatic capture | Lifecycle hooks for passive observation |
|
|
228
|
+
| Session summaries | Structured digests with key decisions and corrections |
|
|
229
|
+
| Interactive dashboard | Drag-and-drop graph, memory editing, export, search highlighting |
|
|
230
|
+
| Config system | `~/.amem/config.json` for full tuning |
|
|
231
|
+
| Benchmark suite | Reproducible Recall@K / MRR / Precision measurements |
|
|
211
232
|
|
|
212
|
-
|
|
233
|
+
<details>
|
|
234
|
+
<summary><strong>View all features across versions</strong></summary>
|
|
213
235
|
|
|
214
|
-
|
|
236
|
+
### v0.8.0
|
|
237
|
+
- `amem init` — auto-configure all AI tools in one command
|
|
238
|
+
- `amem rules` — generate extraction rules
|
|
239
|
+
- `amem dashboard` — web-based memory browser
|
|
215
240
|
|
|
216
|
-
|
|
241
|
+
### v0.7.0
|
|
242
|
+
- Memory import/export with content-hash dedup
|
|
243
|
+
- Confidence decay for stale memories
|
|
244
|
+
- Embedding cache (LRU, 128 entries)
|
|
245
|
+
- Multi-process safe database
|
|
217
246
|
|
|
218
|
-
|
|
247
|
+
### v0.5.x
|
|
248
|
+
- Progressive disclosure (`compact` mode, ~10x token savings)
|
|
249
|
+
- Persistent cross-session reminders with deadlines
|
|
219
250
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
251
|
+
### v0.4.0
|
|
252
|
+
- Lossless conversation log (append-only)
|
|
253
|
+
- Surgical patch system with version history
|
|
254
|
+
- Knowledge graph with typed relations
|
|
255
|
+
- Temporal queries with natural language ranges
|
|
256
|
+
- Full-text search (FTS5)
|
|
257
|
+
|
|
258
|
+
### v0.1.0 — v0.3.0
|
|
259
|
+
- Core store/recall with semantic search
|
|
260
|
+
- Local embeddings (HuggingFace all-MiniLM-L6-v2)
|
|
261
|
+
- SQLite + WAL persistence
|
|
262
|
+
- Memory consolidation engine
|
|
263
|
+
- Project-aware scoping
|
|
228
264
|
|
|
229
|
-
>
|
|
265
|
+
</details>
|
|
230
266
|
|
|
231
267
|
---
|
|
232
268
|
|
|
@@ -236,13 +272,13 @@ Memories are scored and prioritized automatically:
|
|
|
236
272
|
|
|
237
273
|
| Tool | Description |
|
|
238
274
|
|---|---|
|
|
239
|
-
| `memory_store` | Store a memory with type, tags, confidence. Auto-redacts
|
|
240
|
-
| `memory_recall` | Semantic search
|
|
241
|
-
| `memory_detail` | Retrieve full content by ID
|
|
275
|
+
| `memory_store` | Store a memory with type, tags, confidence. Auto-redacts private content and auto-expires contradictions. |
|
|
276
|
+
| `memory_recall` | Semantic search with `compact` mode for progressive disclosure (~10x token savings) |
|
|
277
|
+
| `memory_detail` | Retrieve full content by ID after compact recall |
|
|
242
278
|
| `memory_context` | Load all relevant context for a topic, organized by type |
|
|
243
|
-
| `memory_extract` | Batch-save multiple memories from
|
|
244
|
-
| `memory_forget` | Delete
|
|
245
|
-
| `memory_inject` |
|
|
279
|
+
| `memory_extract` | Batch-save multiple memories from conversation |
|
|
280
|
+
| `memory_forget` | Delete by ID or query (with confirmation) |
|
|
281
|
+
| `memory_inject` | Surface corrections + decisions before coding starts |
|
|
246
282
|
|
|
247
283
|
### Precision & History (5 tools)
|
|
248
284
|
|
|
@@ -251,27 +287,27 @@ Memories are scored and prioritized automatically:
|
|
|
251
287
|
| `memory_patch` | Surgical field-level edit with auto-snapshot |
|
|
252
288
|
| `memory_versions` | View full edit history or restore any version |
|
|
253
289
|
| `memory_search` | Exact full-text search via FTS5 |
|
|
254
|
-
| `memory_since` | Temporal query with natural language ranges |
|
|
255
|
-
| `memory_relate` | Build a knowledge graph between memories |
|
|
290
|
+
| `memory_since` | Temporal query with natural language ranges (`7d`, `2w`, `1h`) |
|
|
291
|
+
| `memory_relate` | Build a typed knowledge graph between memories |
|
|
256
292
|
|
|
257
|
-
### Advanced (5 tools)
|
|
293
|
+
### Advanced (5 tools)
|
|
258
294
|
|
|
259
295
|
| Tool | Description |
|
|
260
296
|
|---|---|
|
|
261
|
-
| `memory_multi_recall` | Multi-strategy search: semantic + FTS5 +
|
|
262
|
-
| `memory_tier` | Move memories between tiers:
|
|
263
|
-
| `memory_expire` | Mark
|
|
264
|
-
| `memory_summarize` | Store
|
|
265
|
-
| `memory_history` | View past session summaries
|
|
297
|
+
| `memory_multi_recall` | Multi-strategy search: semantic + FTS5 + graph + temporal, with configurable weights |
|
|
298
|
+
| `memory_tier` | Move memories between tiers: core / working / archival |
|
|
299
|
+
| `memory_expire` | Mark as no longer valid — preserved for history, excluded from recall |
|
|
300
|
+
| `memory_summarize` | Store structured session summary with decisions, corrections, metrics |
|
|
301
|
+
| `memory_history` | View past session summaries |
|
|
266
302
|
|
|
267
303
|
### Reminders (4 tools)
|
|
268
304
|
|
|
269
305
|
| Tool | Description |
|
|
270
306
|
|---|---|
|
|
271
|
-
| `reminder_set` | Create
|
|
307
|
+
| `reminder_set` | Create reminder with optional deadline and scope |
|
|
272
308
|
| `reminder_list` | List active (or all) reminders, filterable by scope |
|
|
273
|
-
| `reminder_check` |
|
|
274
|
-
| `reminder_complete` | Mark
|
|
309
|
+
| `reminder_check` | Show overdue, today, and upcoming (7 days) |
|
|
310
|
+
| `reminder_complete` | Mark as done (supports partial ID) |
|
|
275
311
|
|
|
276
312
|
### Log & Maintenance (7 tools)
|
|
277
313
|
|
|
@@ -279,38 +315,44 @@ Memories are scored and prioritized automatically:
|
|
|
279
315
|
|---|---|
|
|
280
316
|
| `memory_log` | Append raw conversation turns (lossless, append-only) |
|
|
281
317
|
| `memory_log_recall` | Search or replay log by session, keyword, or recency |
|
|
282
|
-
| `memory_log_cleanup` | Prune old
|
|
283
|
-
| `memory_stats` |
|
|
284
|
-
| `memory_export` | Export
|
|
285
|
-
| `memory_import` | Bulk import
|
|
286
|
-
| `memory_consolidate` | Merge duplicates, prune stale, promote frequent, decay idle
|
|
318
|
+
| `memory_log_cleanup` | Prune old entries with configurable retention |
|
|
319
|
+
| `memory_stats` | Counts, type breakdown, confidence distribution |
|
|
320
|
+
| `memory_export` | Export as Markdown or JSON |
|
|
321
|
+
| `memory_import` | Bulk import from JSON with automatic dedup |
|
|
322
|
+
| `memory_consolidate` | Merge duplicates, prune stale, promote frequent, decay idle |
|
|
287
323
|
|
|
288
324
|
---
|
|
289
325
|
|
|
290
|
-
## Usage
|
|
326
|
+
## Usage Guide
|
|
327
|
+
|
|
328
|
+
### Starting a Session
|
|
329
|
+
|
|
330
|
+
Your AI will automatically load context if rules are installed. You can also ask:
|
|
331
|
+
|
|
332
|
+
> *"Load context for authentication"*
|
|
333
|
+
> *"What corrections do you have for this project?"*
|
|
334
|
+
> *"Check my reminders"*
|
|
335
|
+
|
|
336
|
+
### Storing Memories
|
|
291
337
|
|
|
292
338
|
<details open>
|
|
293
|
-
<summary><strong>
|
|
339
|
+
<summary><strong>Natural language (easiest)</strong></summary>
|
|
294
340
|
|
|
295
|
-
|
|
296
|
-
// Step 1: Compact recall — ~50-100 tokens
|
|
297
|
-
memory_recall({ query: "auth decisions", limit: 5, compact: true })
|
|
298
|
-
// → a1b2c3d4 [decision] Auth service uses JWT tokens... (92%)
|
|
299
|
-
// → e5f6g7h8 [preference] User prefers PostgreSQL... (88%)
|
|
300
|
-
// → i9j0k1l2 [fact] Auth middleware rewrite driven by... (75%)
|
|
341
|
+
Just tell your AI:
|
|
301
342
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
343
|
+
```
|
|
344
|
+
"Remember: we use PostgreSQL, not MongoDB"
|
|
345
|
+
"Store a correction: never use console.log in production"
|
|
346
|
+
"Note that the auth module is in src/auth/ and uses JWT"
|
|
305
347
|
```
|
|
306
348
|
|
|
307
349
|
</details>
|
|
308
350
|
|
|
309
351
|
<details>
|
|
310
|
-
<summary><strong>
|
|
352
|
+
<summary><strong>Explicit tool calls</strong></summary>
|
|
311
353
|
|
|
312
354
|
```js
|
|
313
|
-
// Store a correction — highest priority
|
|
355
|
+
// Store a correction — highest priority
|
|
314
356
|
memory_store({
|
|
315
357
|
content: "Never use 'any' type — always define proper interfaces",
|
|
316
358
|
type: "correction",
|
|
@@ -318,126 +360,90 @@ memory_store({
|
|
|
318
360
|
confidence: 1.0
|
|
319
361
|
})
|
|
320
362
|
|
|
321
|
-
//
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
<details>
|
|
328
|
-
<summary><strong>Patch a memory (surgical, versioned)</strong></summary>
|
|
329
|
-
|
|
330
|
-
```js
|
|
331
|
-
memory_patch({
|
|
332
|
-
id: "a1b2c3d4",
|
|
333
|
-
field: "content",
|
|
334
|
-
value: "Never use 'any' — define interfaces, use 'unknown' for unknown types",
|
|
335
|
-
reason: "added unknown guidance"
|
|
363
|
+
// Batch extract from conversation
|
|
364
|
+
memory_extract({
|
|
365
|
+
memories: [
|
|
366
|
+
{ content: "Uses pnpm, not npm", type: "preference", tags: ["tooling"], confidence: 0.9 },
|
|
367
|
+
{ content: "Auth uses OAuth2 with PKCE", type: "decision", tags: ["auth"], confidence: 0.9 },
|
|
368
|
+
]
|
|
336
369
|
})
|
|
337
|
-
|
|
338
|
-
// Every patch auto-snapshots. Restore any version:
|
|
339
|
-
memory_versions({ memory_id: "a1b2c3d4" })
|
|
340
370
|
```
|
|
341
371
|
|
|
342
372
|
</details>
|
|
343
373
|
|
|
344
|
-
|
|
345
|
-
<summary><strong>Lossless conversation log</strong></summary>
|
|
374
|
+
### Recalling Memories
|
|
346
375
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
memory_log({ session_id: "2025-03-25", role: "user", content: "Let's use OAuth2 with PKCE" })
|
|
350
|
-
memory_log({ session_id: "2025-03-25", role: "assistant", content: "Good call — removes token storage risk..." })
|
|
376
|
+
<details open>
|
|
377
|
+
<summary><strong>Progressive disclosure (recommended)</strong></summary>
|
|
351
378
|
|
|
352
|
-
|
|
353
|
-
|
|
379
|
+
```js
|
|
380
|
+
// Step 1: Compact index — ~50-100 tokens
|
|
381
|
+
memory_recall({ query: "auth decisions", limit: 5, compact: true })
|
|
382
|
+
// → a1b2c3d4 [decision] Auth service uses JWT tokens... (92%)
|
|
383
|
+
// → e5f6g7h8 [correction] Never store tokens in localStorage... (100%)
|
|
354
384
|
|
|
355
|
-
//
|
|
356
|
-
|
|
385
|
+
// Step 2: Full details only for what you need — ~500 tokens
|
|
386
|
+
memory_detail({ ids: ["a1b2c3d4", "e5f6g7h8"] })
|
|
357
387
|
```
|
|
358
388
|
|
|
359
389
|
</details>
|
|
360
390
|
|
|
361
391
|
<details>
|
|
362
|
-
<summary><strong>
|
|
392
|
+
<summary><strong>Multi-strategy search (most thorough)</strong></summary>
|
|
363
393
|
|
|
364
394
|
```js
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
strength: 0.9
|
|
395
|
+
// Combines 4 strategies: semantic + FTS5 + graph traversal + temporal
|
|
396
|
+
memory_multi_recall({
|
|
397
|
+
query: "authentication architecture",
|
|
398
|
+
limit: 10,
|
|
399
|
+
weights: { semantic: 0.4, fts: 0.3, graph: 0.15, temporal: 0.15 }
|
|
371
400
|
})
|
|
372
|
-
|
|
373
|
-
// View connections
|
|
374
|
-
memory_relate({ action: "graph", memory_id: "decision-abc" })
|
|
375
401
|
```
|
|
376
402
|
|
|
377
|
-
Relation types: `supports`, `contradicts`, `depends_on`, `supersedes`, `related_to`, `caused_by`, `implements` — or define your own.
|
|
378
|
-
|
|
379
403
|
</details>
|
|
380
404
|
|
|
381
405
|
<details>
|
|
382
|
-
<summary><strong>
|
|
406
|
+
<summary><strong>Exact keyword search</strong></summary>
|
|
383
407
|
|
|
384
408
|
```js
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
409
|
+
memory_search({ query: "OAuth PKCE" }) // exact terms
|
|
410
|
+
memory_search({ query: '"event sourcing"' }) // phrase match
|
|
411
|
+
memory_search({ query: "auth* NOT legacy" }) // FTS5 boolean syntax
|
|
388
412
|
```
|
|
389
413
|
|
|
390
414
|
</details>
|
|
391
415
|
|
|
416
|
+
### Managing Memories
|
|
417
|
+
|
|
392
418
|
<details>
|
|
393
|
-
<summary><strong>
|
|
419
|
+
<summary><strong>Edit a memory (surgical, versioned)</strong></summary>
|
|
394
420
|
|
|
395
421
|
```js
|
|
396
|
-
//
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
422
|
+
// Patch a single field — auto-snapshots for rollback
|
|
423
|
+
memory_patch({
|
|
424
|
+
id: "a1b2c3d4",
|
|
425
|
+
field: "content",
|
|
426
|
+
value: "Never use 'any' — use interfaces or 'unknown'",
|
|
427
|
+
reason: "added unknown guidance"
|
|
401
428
|
})
|
|
402
429
|
|
|
403
|
-
//
|
|
404
|
-
|
|
405
|
-
// → [OVERDUE] Review PR #42 (3/27/2026) [a1b2c3d4]
|
|
406
|
-
// → [TODAY] Deploy auth service (3/25/2026) [e5f6g7h8]
|
|
407
|
-
// → [upcoming] Write quarterly report (3/31/2026) [i9j0k1l2]
|
|
408
|
-
|
|
409
|
-
// Mark as done
|
|
410
|
-
reminder_complete({ id: "a1b2c3d4" })
|
|
411
|
-
// → Completed: "Review PR #42"
|
|
412
|
-
|
|
413
|
-
// List all active reminders
|
|
414
|
-
reminder_list({ include_completed: false })
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
</details>
|
|
418
|
-
|
|
419
|
-
<details>
|
|
420
|
-
<summary><strong>Full-text search (FTS5)</strong></summary>
|
|
430
|
+
// View history
|
|
431
|
+
memory_versions({ memory_id: "a1b2c3d4" })
|
|
421
432
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
memory_search({ query: '"event sourcing"' }) // phrase match
|
|
425
|
-
memory_search({ query: "auth* NOT legacy" }) // FTS5 boolean syntax
|
|
433
|
+
// Restore a previous version
|
|
434
|
+
memory_versions({ memory_id: "a1b2c3d4", restore_version_id: "v1b2c3d4" })
|
|
426
435
|
```
|
|
427
436
|
|
|
428
437
|
</details>
|
|
429
438
|
|
|
430
439
|
<details>
|
|
431
|
-
<summary><strong>
|
|
440
|
+
<summary><strong>Expire outdated memories</strong></summary>
|
|
432
441
|
|
|
433
442
|
```js
|
|
434
|
-
// Mark
|
|
435
|
-
memory_expire({
|
|
436
|
-
id: "a1b2c3d4",
|
|
437
|
-
reason: "Migrated from REST to GraphQL"
|
|
438
|
-
})
|
|
443
|
+
// Mark as expired — preserved for history, excluded from recall
|
|
444
|
+
memory_expire({ id: "a1b2c3d4", reason: "Migrated from REST to GraphQL" })
|
|
439
445
|
|
|
440
|
-
// Store the
|
|
446
|
+
// Store the replacement — contradictions are also auto-detected
|
|
441
447
|
memory_store({
|
|
442
448
|
content: "API uses GraphQL with Apollo Server",
|
|
443
449
|
type: "decision",
|
|
@@ -452,10 +458,10 @@ memory_since({ since: "2025-01-01", until: "2025-03-01", type: "decision" })
|
|
|
452
458
|
</details>
|
|
453
459
|
|
|
454
460
|
<details>
|
|
455
|
-
<summary><strong>
|
|
461
|
+
<summary><strong>Promote to core tier</strong></summary>
|
|
456
462
|
|
|
457
463
|
```js
|
|
458
|
-
//
|
|
464
|
+
// Core memories are always injected at session start
|
|
459
465
|
memory_tier({ id: "a1b2c3d4", tier: "core" })
|
|
460
466
|
|
|
461
467
|
// List all core memories
|
|
@@ -467,22 +473,55 @@ memory_tier({ id: "a1b2c3d4", tier: "archival" })
|
|
|
467
473
|
|
|
468
474
|
</details>
|
|
469
475
|
|
|
476
|
+
### Knowledge Graph
|
|
477
|
+
|
|
470
478
|
<details>
|
|
471
|
-
<summary><strong>
|
|
479
|
+
<summary><strong>Link related memories</strong></summary>
|
|
472
480
|
|
|
473
481
|
```js
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
482
|
+
memory_relate({
|
|
483
|
+
action: "relate",
|
|
484
|
+
from_id: "decision-abc",
|
|
485
|
+
to_id: "pattern-xyz",
|
|
486
|
+
relation_type: "supports",
|
|
487
|
+
strength: 0.9
|
|
479
488
|
})
|
|
489
|
+
|
|
490
|
+
// View all connections for a memory
|
|
491
|
+
memory_relate({ action: "graph", memory_id: "decision-abc" })
|
|
480
492
|
```
|
|
481
493
|
|
|
494
|
+
Relation types: `supports`, `contradicts`, `depends_on`, `supersedes`, `related_to`, `caused_by`, `implements` — or define your own.
|
|
495
|
+
|
|
482
496
|
</details>
|
|
483
497
|
|
|
498
|
+
### Reminders
|
|
499
|
+
|
|
484
500
|
<details>
|
|
485
|
-
<summary><strong>
|
|
501
|
+
<summary><strong>Cross-session deadline tracking</strong></summary>
|
|
502
|
+
|
|
503
|
+
```js
|
|
504
|
+
reminder_set({
|
|
505
|
+
content: "Review PR #42",
|
|
506
|
+
due_at: 1743033600000,
|
|
507
|
+
scope: "global"
|
|
508
|
+
})
|
|
509
|
+
|
|
510
|
+
// Check what's due (your AI does this automatically at session start)
|
|
511
|
+
reminder_check({})
|
|
512
|
+
// → [OVERDUE] Review PR #42
|
|
513
|
+
// → [TODAY] Deploy auth service
|
|
514
|
+
// → [upcoming] Write quarterly report
|
|
515
|
+
|
|
516
|
+
reminder_complete({ id: "a1b2c3d4" })
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
</details>
|
|
520
|
+
|
|
521
|
+
### Privacy
|
|
522
|
+
|
|
523
|
+
<details>
|
|
524
|
+
<summary><strong>Protect sensitive data</strong></summary>
|
|
486
525
|
|
|
487
526
|
```js
|
|
488
527
|
// Private blocks are stripped before storage
|
|
@@ -493,16 +532,19 @@ memory_store({
|
|
|
493
532
|
})
|
|
494
533
|
// Stored as: "DB password is [REDACTED], connect to prod at db.example.com"
|
|
495
534
|
|
|
496
|
-
// API keys
|
|
535
|
+
// API keys, tokens, and passwords are auto-redacted by pattern matching
|
|
536
|
+
// Configure patterns in ~/.amem/config.json
|
|
497
537
|
```
|
|
498
538
|
|
|
499
539
|
</details>
|
|
500
540
|
|
|
541
|
+
### Session Summaries
|
|
542
|
+
|
|
501
543
|
<details>
|
|
502
|
-
<summary><strong>
|
|
544
|
+
<summary><strong>Structured session digests</strong></summary>
|
|
503
545
|
|
|
504
546
|
```js
|
|
505
|
-
// Summarize at session end
|
|
547
|
+
// Summarize at session end (also done automatically by Stop hook)
|
|
506
548
|
memory_summarize({
|
|
507
549
|
session_id: "sess-2025-03-25",
|
|
508
550
|
summary: "Redesigned auth flow from session tokens to JWT",
|
|
@@ -511,7 +553,7 @@ memory_summarize({
|
|
|
511
553
|
memories_extracted: 7
|
|
512
554
|
})
|
|
513
555
|
|
|
514
|
-
// Review past sessions
|
|
556
|
+
// Review what happened in past sessions
|
|
515
557
|
memory_history({ limit: 5 })
|
|
516
558
|
```
|
|
517
559
|
|
|
@@ -519,6 +561,53 @@ memory_history({ limit: 5 })
|
|
|
519
561
|
|
|
520
562
|
---
|
|
521
563
|
|
|
564
|
+
## Dashboard
|
|
565
|
+
|
|
566
|
+
Launch the interactive web dashboard:
|
|
567
|
+
|
|
568
|
+
```bash
|
|
569
|
+
amem-cli dashboard # Opens at localhost:3333
|
|
570
|
+
amem-cli dashboard --port=8080 # Custom port
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
**Features:**
|
|
574
|
+
- Memory list with search, type filter, and tier filter
|
|
575
|
+
- Search term highlighting
|
|
576
|
+
- Inline actions: Promote to Core, Demote, Expire
|
|
577
|
+
- Export as JSON or Markdown with one click
|
|
578
|
+
- Interactive knowledge graph (drag nodes, click to inspect)
|
|
579
|
+
- Confidence distribution and type breakdown charts
|
|
580
|
+
- Session summaries timeline
|
|
581
|
+
- Reminders with status badges
|
|
582
|
+
- Recent conversation log
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
## CLI Reference
|
|
587
|
+
|
|
588
|
+
```bash
|
|
589
|
+
# Setup
|
|
590
|
+
amem-cli init # Auto-configure AI tools
|
|
591
|
+
amem-cli rules # Generate extraction rules
|
|
592
|
+
amem-cli hooks # Install automatic capture hooks
|
|
593
|
+
amem-cli hooks --uninstall # Remove hooks
|
|
594
|
+
|
|
595
|
+
# Dashboard
|
|
596
|
+
amem-cli dashboard # Web dashboard (localhost:3333)
|
|
597
|
+
amem-cli dashboard --port=8080 # Custom port
|
|
598
|
+
|
|
599
|
+
# Memory operations
|
|
600
|
+
amem-cli recall "authentication" # Semantic search
|
|
601
|
+
amem-cli stats # Statistics
|
|
602
|
+
amem-cli list # List all memories
|
|
603
|
+
amem-cli list --type correction # Filter by type
|
|
604
|
+
amem-cli export --file memories.md # Export to file
|
|
605
|
+
amem-cli forget abc12345 # Delete by short ID
|
|
606
|
+
amem-cli reset --confirm # Wipe all data
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
---
|
|
610
|
+
|
|
522
611
|
## Architecture
|
|
523
612
|
|
|
524
613
|
```
|
|
@@ -529,20 +618,21 @@ memory_history({ limit: 5 })
|
|
|
529
618
|
│ MCP Protocol │ Lifecycle Hooks
|
|
530
619
|
│ (stdio) │ (PostToolUse, Stop)
|
|
531
620
|
┌────────▼─────────────────────▼───────────────┐
|
|
532
|
-
│
|
|
621
|
+
│ amem MCP Server │
|
|
533
622
|
│ │
|
|
534
623
|
│ 28 Tools · 6 Resources · 2 Prompts │
|
|
535
624
|
│ │
|
|
536
625
|
│ Multi-Strategy Retrieval Pipeline │
|
|
537
626
|
│ [Semantic] + [FTS5] + [Graph] + [Temporal] │
|
|
627
|
+
│ ↓ optional cross-encoder rerank │
|
|
538
628
|
│ │
|
|
539
629
|
│ ┌────────────────────────────────────┐ │
|
|
540
630
|
│ │ SQLite + WAL + FTS5 │ │
|
|
541
631
|
│ │ ~/.amem/memory.db │ │
|
|
542
632
|
│ │ │ │
|
|
543
|
-
│ │ memories (tiered
|
|
633
|
+
│ │ memories (tiered+temporal│ │
|
|
544
634
|
│ │ conversation_log (lossless) │ │
|
|
545
|
-
│ │ memory_versions (history)
|
|
635
|
+
│ │ memory_versions (edit history) │ │
|
|
546
636
|
│ │ memory_relations (temporal graph)│ │
|
|
547
637
|
│ │ session_summaries (digests) │ │
|
|
548
638
|
│ │ reminders (cross-session) │ │
|
|
@@ -553,6 +643,19 @@ memory_history({ limit: 5 })
|
|
|
553
643
|
└──────────────────────────────────────────────┘
|
|
554
644
|
```
|
|
555
645
|
|
|
646
|
+
### Ranking Formula
|
|
647
|
+
|
|
648
|
+
```
|
|
649
|
+
score = relevance × recency × confidence × importance
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
| Factor | How it works |
|
|
653
|
+
|---|---|
|
|
654
|
+
| **Relevance** | Cosine similarity via local embeddings; keyword fallback |
|
|
655
|
+
| **Recency** | Exponential decay (`0.995^hours`) |
|
|
656
|
+
| **Confidence** | Reinforced by repeated confirmation (0-1) |
|
|
657
|
+
| **Importance** | Type-based: corrections `1.0` → facts `0.4` |
|
|
658
|
+
|
|
556
659
|
### Benchmark Results
|
|
557
660
|
|
|
558
661
|
Run `npx vitest run benchmarks/` to reproduce. Corpus: 34 realistic developer memories, 16 queries (exact, paraphrased, topical).
|
|
@@ -560,30 +663,19 @@ Run `npx vitest run benchmarks/` to reproduce. Corpus: 34 realistic developer me
|
|
|
560
663
|
| Strategy | Recall@5 | Recall@10 | MRR | Precision@5 |
|
|
561
664
|
|---|---|---|---|---|
|
|
562
665
|
| Keyword-only (no embeddings) | 34.4% | 62.0% | 36.7% | 13.8% |
|
|
563
|
-
| FTS5-only | 31.3% | 31.3% | 31.3% |
|
|
666
|
+
| FTS5-only | 31.3% | 31.3% | 31.3% | --- |
|
|
564
667
|
| Multi-strategy (FTS + graph + temporal) | 31.3% | 31.3% | 31.3% | 25.0% |
|
|
565
668
|
| **Multi-strategy + embeddings** | **~70%+** | **~85%+** | **~75%+** | **~35%+** |
|
|
566
669
|
| **+ cross-encoder reranking** | **~80%+** | **~90%+** | **~85%+** | **~45%+** |
|
|
567
670
|
|
|
568
|
-
*
|
|
569
|
-
|
|
570
|
-
### Ranking Formula
|
|
571
|
-
|
|
572
|
-
```
|
|
573
|
-
score = relevance × recency × confidence × importance
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
| Factor | How it works |
|
|
577
|
-
|---|---|
|
|
578
|
-
| **Relevance** | Cosine similarity via local embeddings, keyword fallback |
|
|
579
|
-
| **Recency** | Exponential decay (`0.995^hours`) |
|
|
580
|
-
| **Confidence** | Reinforced by repeated confirmation |
|
|
581
|
-
| **Importance** | Type-based: corrections `1.0` → facts `0.4` |
|
|
671
|
+
*Keyword-only scores are the floor — retrieval gracefully degrades without embeddings.*
|
|
582
672
|
|
|
583
673
|
---
|
|
584
674
|
|
|
585
675
|
## MCP Resources
|
|
586
676
|
|
|
677
|
+
These are automatically available to your AI tool:
|
|
678
|
+
|
|
587
679
|
| URI | Description |
|
|
588
680
|
|---|---|
|
|
589
681
|
| `amem://corrections` | All active corrections (hard constraints) |
|
|
@@ -595,36 +687,19 @@ score = relevance × recency × confidence × importance
|
|
|
595
687
|
|
|
596
688
|
---
|
|
597
689
|
|
|
598
|
-
## CLI
|
|
599
|
-
|
|
600
|
-
```bash
|
|
601
|
-
amem-cli init # Auto-configure AI tools
|
|
602
|
-
amem-cli rules # Generate auto-extraction rules
|
|
603
|
-
amem-cli hooks # Install automatic memory capture hooks
|
|
604
|
-
amem-cli hooks --uninstall # Remove hooks
|
|
605
|
-
amem-cli dashboard # Open web dashboard
|
|
606
|
-
amem-cli recall "authentication" # Semantic search
|
|
607
|
-
amem-cli stats # Statistics
|
|
608
|
-
amem-cli list # List all memories
|
|
609
|
-
amem-cli list --type correction # Filter by type
|
|
610
|
-
amem-cli export --file memories.md # Export to file
|
|
611
|
-
amem-cli forget abc12345 # Delete by short ID
|
|
612
|
-
amem-cli reset --confirm # Wipe all data
|
|
613
|
-
```
|
|
614
|
-
|
|
615
|
-
---
|
|
616
|
-
|
|
617
690
|
## Configuration
|
|
618
691
|
|
|
619
|
-
|
|
692
|
+
### Environment Variables
|
|
620
693
|
|
|
621
694
|
| Variable | Default | Description |
|
|
622
695
|
|---|---|---|
|
|
623
696
|
| `AMEM_DIR` | `~/.amem` | Storage directory |
|
|
624
697
|
| `AMEM_DB` | `~/.amem/memory.db` | Database path |
|
|
625
|
-
| `AMEM_PROJECT` | *(auto from git)* | Project scope |
|
|
698
|
+
| `AMEM_PROJECT` | *(auto from git)* | Project scope override |
|
|
699
|
+
|
|
700
|
+
### Config File (`~/.amem/config.json`)
|
|
626
701
|
|
|
627
|
-
|
|
702
|
+
Created automatically with defaults. Edit to customize:
|
|
628
703
|
|
|
629
704
|
```json
|
|
630
705
|
{
|
|
@@ -633,11 +708,15 @@ amem-cli reset --confirm # Wipe all data
|
|
|
633
708
|
"ftsWeight": 0.3,
|
|
634
709
|
"graphWeight": 0.15,
|
|
635
710
|
"temporalWeight": 0.15,
|
|
636
|
-
"maxCandidates": 50000
|
|
711
|
+
"maxCandidates": 50000,
|
|
712
|
+
"rerankerEnabled": false,
|
|
713
|
+
"rerankerTopK": 20
|
|
637
714
|
},
|
|
638
715
|
"privacy": {
|
|
639
716
|
"enablePrivateTags": true,
|
|
640
|
-
"redactPatterns": [
|
|
717
|
+
"redactPatterns": [
|
|
718
|
+
"(?:api[_-]?key|secret|token|password)\\s*[:=]\\s*['\"]?[A-Za-z0-9_\\-\\.]{8,}"
|
|
719
|
+
]
|
|
641
720
|
},
|
|
642
721
|
"tiers": {
|
|
643
722
|
"coreMaxTokens": 500,
|
|
@@ -658,11 +737,12 @@ amem-cli reset --confirm # Wipe all data
|
|
|
658
737
|
| Layer | Technology |
|
|
659
738
|
|---|---|
|
|
660
739
|
| Protocol | MCP SDK ^1.25 |
|
|
661
|
-
| Language | TypeScript 5.6+, strict mode
|
|
740
|
+
| Language | TypeScript 5.6+, strict mode |
|
|
662
741
|
| Database | SQLite + WAL + FTS5 |
|
|
663
742
|
| Embeddings | HuggingFace Xenova/all-MiniLM-L6-v2 (local, 80MB) |
|
|
743
|
+
| Reranking | Xenova/ms-marco-MiniLM-L-6-v2 (optional, local) |
|
|
664
744
|
| Validation | Zod 3.25+ with `.strict()` schemas |
|
|
665
|
-
| Testing | Vitest —
|
|
745
|
+
| Testing | Vitest — 311 tests across 20 suites |
|
|
666
746
|
| CI/CD | GitHub Actions → npm publish on release |
|
|
667
747
|
|
|
668
748
|
---
|
|
@@ -673,7 +753,7 @@ amem-cli reset --confirm # Wipe all data
|
|
|
673
753
|
git clone https://github.com/amanasmuei/amem.git
|
|
674
754
|
cd amem && npm install
|
|
675
755
|
npm run build # zero TS errors
|
|
676
|
-
npm test #
|
|
756
|
+
npm test # 311 tests pass
|
|
677
757
|
```
|
|
678
758
|
|
|
679
759
|
PRs must pass CI before merge. See [Issues](https://github.com/amanasmuei/amem/issues) for open tasks.
|
package/dist/dashboard.js
CHANGED
|
@@ -74,7 +74,26 @@ a{color:var(--decision);text-decoration:none}
|
|
|
74
74
|
.mem-card .mem-meta .tag{background:var(--card);border:1px solid var(--border);border-radius:4px;padding:1px 6px}
|
|
75
75
|
|
|
76
76
|
/* knowledge graph */
|
|
77
|
-
#graph-svg{width:100%;height:
|
|
77
|
+
#graph-svg{width:100%;height:460px;border-radius:6px;background:var(--bg);cursor:grab}
|
|
78
|
+
#graph-svg:active{cursor:grabbing}
|
|
79
|
+
#graph-svg circle{cursor:pointer;transition:r 0.15s}
|
|
80
|
+
#graph-svg circle:hover{r:12}
|
|
81
|
+
.graph-tooltip{position:absolute;background:var(--card);border:1px solid var(--border);border-radius:6px;padding:10px 14px;font-size:0.8rem;max-width:300px;pointer-events:none;z-index:10;box-shadow:0 4px 12px rgba(0,0,0,0.4)}
|
|
82
|
+
|
|
83
|
+
/* memory actions */
|
|
84
|
+
.mem-actions{display:flex;gap:6px;margin-top:6px}
|
|
85
|
+
.mem-actions button{background:var(--card);border:1px solid var(--border);color:var(--text);border-radius:4px;padding:3px 10px;font-size:0.7rem;cursor:pointer;transition:all 0.15s}
|
|
86
|
+
.mem-actions button:hover{background:var(--border);color:#fff}
|
|
87
|
+
.mem-actions .btn-core{border-color:var(--correction)}
|
|
88
|
+
.mem-actions .btn-expire{border-color:var(--muted)}
|
|
89
|
+
|
|
90
|
+
/* export bar */
|
|
91
|
+
.export-bar{display:flex;gap:10px;justify-content:flex-end;margin-bottom:10px}
|
|
92
|
+
.export-bar button{background:var(--decision);color:#fff;border:none;border-radius:6px;padding:6px 16px;font-size:0.8rem;cursor:pointer;font-weight:600;transition:opacity 0.15s}
|
|
93
|
+
.export-bar button:hover{opacity:0.85}
|
|
94
|
+
|
|
95
|
+
/* highlight */
|
|
96
|
+
.highlight{background:rgba(88,166,255,0.2);border-radius:2px;padding:0 2px}
|
|
78
97
|
|
|
79
98
|
/* reminders */
|
|
80
99
|
.reminder-list{max-height:360px;overflow-y:auto;display:flex;flex-direction:column;gap:6px}
|
|
@@ -122,6 +141,10 @@ a{color:var(--decision);text-decoration:none}
|
|
|
122
141
|
<!-- Memory list -->
|
|
123
142
|
<div class="card full" id="mem-section">
|
|
124
143
|
<h2>Memories</h2>
|
|
144
|
+
<div class="export-bar">
|
|
145
|
+
<button onclick="exportMemories('json')">Export JSON</button>
|
|
146
|
+
<button onclick="exportMemories('markdown')">Export Markdown</button>
|
|
147
|
+
</div>
|
|
125
148
|
<div class="mem-controls">
|
|
126
149
|
<input type="text" id="mem-search" placeholder="Search memories..."/>
|
|
127
150
|
<select id="mem-type">
|
|
@@ -146,6 +169,7 @@ a{color:var(--decision);text-decoration:none}
|
|
|
146
169
|
<!-- Knowledge graph -->
|
|
147
170
|
<div class="card" id="graph-card">
|
|
148
171
|
<h2>Knowledge Graph</h2>
|
|
172
|
+
<div id="graph-tooltip" class="graph-tooltip" style="display:none"></div>
|
|
149
173
|
<svg id="graph-svg"></svg>
|
|
150
174
|
</div>
|
|
151
175
|
|
|
@@ -226,6 +250,17 @@ a{color:var(--decision);text-decoration:none}
|
|
|
226
250
|
setHTML($('conf-bars'), bar('High',conf.high,'conf-high')+bar('Medium',conf.medium,'conf-med')+bar('Low',conf.low,'conf-low'));
|
|
227
251
|
}
|
|
228
252
|
|
|
253
|
+
var currentSearchQuery='';
|
|
254
|
+
|
|
255
|
+
function highlightText(text,query){
|
|
256
|
+
if(!query) return esc(text);
|
|
257
|
+
var escaped=esc(text);
|
|
258
|
+
try{
|
|
259
|
+
var q=query.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g,'\\\\$&');
|
|
260
|
+
return escaped.replace(new RegExp('('+q+')','gi'),'<span class="highlight">$1</span>');
|
|
261
|
+
}catch(e){return escaped}
|
|
262
|
+
}
|
|
263
|
+
|
|
229
264
|
function renderMemories(memories){
|
|
230
265
|
var el=$('mem-list');
|
|
231
266
|
if(!memories.length){setHTML(el,'<div class="empty">No memories found</div>');return}
|
|
@@ -235,13 +270,16 @@ a{color:var(--decision);text-decoration:none}
|
|
|
235
270
|
var tierBadge = m.tier && m.tier !== 'archival' ? '<span class="type-badge" style="background:'+(m.tier==='core'?'#f0883e':'#58a6ff')+'">'+esc(m.tier)+'</span>' : '';
|
|
236
271
|
var expiredBadge = m.validUntil ? '<span class="type-badge" style="background:#f85149;opacity:0.7">expired</span>' : '';
|
|
237
272
|
var validInfo = m.validFrom ? '<span>Valid: '+new Date(m.validFrom).toISOString().slice(0,10)+(m.validUntil?' → '+new Date(m.validUntil).toISOString().slice(0,10):' → now')+'</span>' : '';
|
|
273
|
+
var contentHtml = highlightText(m.content, currentSearchQuery);
|
|
274
|
+
var sid=esc(m.id.slice(0,8));
|
|
275
|
+
var tierLabel=m.tier||'archival';
|
|
238
276
|
return '<div class="mem-card"'+(m.validUntil?' style="opacity:0.6"':'')+'>'+
|
|
239
277
|
'<div class="mem-head">'+
|
|
240
278
|
'<span class="type-badge" style="background:'+color+'">'+esc(m.type)+'</span>'+
|
|
241
279
|
tierBadge+expiredBadge+
|
|
242
|
-
'<code class="mono" style="color:var(--muted);font-size:0.7rem">'+
|
|
280
|
+
'<code class="mono" style="color:var(--muted);font-size:0.7rem">'+sid+'</code>'+
|
|
243
281
|
'</div>'+
|
|
244
|
-
'<div class="mem-content">'+
|
|
282
|
+
'<div class="mem-content">'+contentHtml+'</div>'+
|
|
245
283
|
'<div class="mem-meta">'+
|
|
246
284
|
'<span>Confidence: '+Math.round(m.confidence*100)+'%</span>'+
|
|
247
285
|
'<span>'+timeAgo(m.createdAt)+'</span>'+
|
|
@@ -249,6 +287,11 @@ a{color:var(--decision);text-decoration:none}
|
|
|
249
287
|
(m.scope?'<span>Scope: '+esc(m.scope)+'</span>':'')+
|
|
250
288
|
validInfo+
|
|
251
289
|
(tags?' '+tags:'')+
|
|
290
|
+
'</div>'+
|
|
291
|
+
'<div class="mem-actions">'+
|
|
292
|
+
(tierLabel!=='core'?'<button class="btn-core" data-action="tier:core:'+sid+'">Promote to Core</button>':
|
|
293
|
+
'<button data-action="tier:archival:'+sid+'">Demote</button>')+
|
|
294
|
+
(!m.validUntil?'<button class="btn-expire" data-action="expire::'+sid+'">Expire</button>':'')+
|
|
252
295
|
'</div></div>';
|
|
253
296
|
}).join(''));
|
|
254
297
|
}
|
|
@@ -257,6 +300,7 @@ a{color:var(--decision);text-decoration:none}
|
|
|
257
300
|
var q=($('mem-search').value||'').toLowerCase();
|
|
258
301
|
var t=$('mem-type').value;
|
|
259
302
|
var tier=$('mem-tier')?$('mem-tier').value:'';
|
|
303
|
+
currentSearchQuery=q;
|
|
260
304
|
var list=allMemories;
|
|
261
305
|
if(q) list=list.filter(function(m){return m.content.toLowerCase().indexOf(q)!==-1});
|
|
262
306
|
if(t) list=list.filter(function(m){return m.type===t});
|
|
@@ -318,6 +362,11 @@ a{color:var(--decision);text-decoration:none}
|
|
|
318
362
|
}
|
|
319
363
|
}
|
|
320
364
|
|
|
365
|
+
// Store for interactive use
|
|
366
|
+
graphNodes=nodes;
|
|
367
|
+
graphEdges=edges;
|
|
368
|
+
graphNodeMap=nodeMap;
|
|
369
|
+
|
|
321
370
|
// render SVG elements (all text escaped via esc())
|
|
322
371
|
var html='';
|
|
323
372
|
for(i=0;i<edges.length;i++){
|
|
@@ -329,7 +378,7 @@ a{color:var(--decision);text-decoration:none}
|
|
|
329
378
|
}
|
|
330
379
|
for(i=0;i<nodes.length;i++){
|
|
331
380
|
var color=TYPE_COLORS[nodes[i].type]||'#8b949e';
|
|
332
|
-
html+='<circle cx="'+nodes[i].x+'" cy="'+nodes[i].y+'" r="8" fill="'+color+'" stroke="#0d1117" stroke-width="2"/>';
|
|
381
|
+
html+='<circle data-nid="'+esc(nodes[i].id)+'" cx="'+nodes[i].x+'" cy="'+nodes[i].y+'" r="8" fill="'+color+'" stroke="#0d1117" stroke-width="2"/>';
|
|
333
382
|
html+='<text x="'+nodes[i].x+'" y="'+(nodes[i].y+20)+'" fill="'+color+'" font-size="10" text-anchor="middle" font-family="-apple-system,sans-serif">'+esc(nodes[i].label.slice(0,24))+'</text>';
|
|
334
383
|
}
|
|
335
384
|
setHTML(svg, html);
|
|
@@ -418,7 +467,134 @@ a{color:var(--decision);text-decoration:none}
|
|
|
418
467
|
$('mem-type').addEventListener('change',filterMemories);
|
|
419
468
|
if($('mem-tier')) $('mem-tier').addEventListener('change',filterMemories);
|
|
420
469
|
|
|
470
|
+
// -- Memory actions (delegated) --
|
|
471
|
+
document.addEventListener('click',function(e){
|
|
472
|
+
var btn=e.target;
|
|
473
|
+
if(!btn||!btn.dataset||!btn.dataset.action) return;
|
|
474
|
+
var parts=btn.dataset.action.split(':');
|
|
475
|
+
var action=parts[0],val=parts[1],id=parts[2];
|
|
476
|
+
if(!id) return;
|
|
477
|
+
|
|
478
|
+
var url='';
|
|
479
|
+
if(action==='tier') url='/api/action/tier?id='+encodeURIComponent(id)+'&tier='+encodeURIComponent(val);
|
|
480
|
+
else if(action==='expire') url='/api/action/expire?id='+encodeURIComponent(id);
|
|
481
|
+
else return;
|
|
482
|
+
|
|
483
|
+
fetch(url,{method:'POST'}).then(function(r){
|
|
484
|
+
if(r.ok) loadAll();
|
|
485
|
+
else r.text().then(function(t){alert('Error: '+t)});
|
|
486
|
+
}).catch(function(err){alert('Error: '+err.message)});
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
// -- Export --
|
|
490
|
+
window.exportMemories=function(format){
|
|
491
|
+
fetch('/api/memories?limit=10000').then(function(r){return r.json()}).then(function(data){
|
|
492
|
+
var content,filename,mime;
|
|
493
|
+
if(format==='json'){
|
|
494
|
+
content=JSON.stringify(data,null,2);
|
|
495
|
+
filename='amem-export.json';
|
|
496
|
+
mime='application/json';
|
|
497
|
+
} else {
|
|
498
|
+
var lines=['# amem Memory Export\\n','*Exported: '+new Date().toISOString()+'*','*Total: '+data.length+' memories*\\n'];
|
|
499
|
+
var types=['correction','decision','pattern','preference','topology','fact'];
|
|
500
|
+
for(var ti=0;ti<types.length;ti++){
|
|
501
|
+
var type=types[ti];
|
|
502
|
+
var mems=data.filter(function(m){return m.type===type});
|
|
503
|
+
if(!mems.length) continue;
|
|
504
|
+
lines.push('## '+type.charAt(0).toUpperCase()+type.slice(1)+'s\\n');
|
|
505
|
+
for(var mi=0;mi<mems.length;mi++){
|
|
506
|
+
lines.push('- **'+mems[mi].content+'** ('+Math.round(mems[mi].confidence*100)+'% confidence)');
|
|
507
|
+
if(mems[mi].tags&&mems[mi].tags.length) lines.push(' Tags: '+mems[mi].tags.join(', '));
|
|
508
|
+
lines.push('');
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
content=lines.join('\\n');
|
|
512
|
+
filename='amem-export.md';
|
|
513
|
+
mime='text/markdown';
|
|
514
|
+
}
|
|
515
|
+
var blob=new Blob([content],{type:mime});
|
|
516
|
+
var a=document.createElement('a');
|
|
517
|
+
a.href=URL.createObjectURL(blob);
|
|
518
|
+
a.download=filename;
|
|
519
|
+
a.click();
|
|
520
|
+
URL.revokeObjectURL(a.href);
|
|
521
|
+
});
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
// -- Interactive Graph (drag, click-to-inspect) --
|
|
525
|
+
var dragNode=null, dragOffset={x:0,y:0}, graphNodes=[], graphNodeMap={}, graphEdges=[];
|
|
526
|
+
|
|
527
|
+
function makeGraphInteractive(){
|
|
528
|
+
var svg=$('graph-svg');
|
|
529
|
+
var tooltip=$('graph-tooltip');
|
|
530
|
+
if(!svg||!tooltip) return;
|
|
531
|
+
|
|
532
|
+
svg.addEventListener('mousedown',function(e){
|
|
533
|
+
var circle=e.target;
|
|
534
|
+
if(circle.tagName!=='circle') return;
|
|
535
|
+
var nid=circle.dataset.nid;
|
|
536
|
+
if(!nid) return;
|
|
537
|
+
dragNode=graphNodeMap[nid];
|
|
538
|
+
if(!dragNode) return;
|
|
539
|
+
var rect=svg.getBoundingClientRect();
|
|
540
|
+
dragOffset.x=e.clientX-rect.left-dragNode.x;
|
|
541
|
+
dragOffset.y=e.clientY-rect.top-dragNode.y;
|
|
542
|
+
e.preventDefault();
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
svg.addEventListener('mousemove',function(e){
|
|
546
|
+
if(!dragNode) return;
|
|
547
|
+
var rect=svg.getBoundingClientRect();
|
|
548
|
+
dragNode.x=e.clientX-rect.left-dragOffset.x;
|
|
549
|
+
dragNode.y=e.clientY-rect.top-dragOffset.y;
|
|
550
|
+
redrawGraph();
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
document.addEventListener('mouseup',function(){dragNode=null});
|
|
554
|
+
|
|
555
|
+
svg.addEventListener('click',function(e){
|
|
556
|
+
var circle=e.target;
|
|
557
|
+
if(circle.tagName!=='circle') return;
|
|
558
|
+
var nid=circle.dataset.nid;
|
|
559
|
+
if(!nid) return;
|
|
560
|
+
var n=graphNodeMap[nid];
|
|
561
|
+
if(!n) return;
|
|
562
|
+
var rect=svg.getBoundingClientRect();
|
|
563
|
+
tooltip.style.display='block';
|
|
564
|
+
tooltip.style.left=(e.clientX-rect.left+15)+'px';
|
|
565
|
+
tooltip.style.top=(e.clientY-rect.top-10)+'px';
|
|
566
|
+
setHTML(tooltip,
|
|
567
|
+
'<div style="margin-bottom:4px"><span class="type-badge" style="background:'+(TYPE_COLORS[n.type]||'#8b949e')+'">'+esc(n.type)+'</span> <code class="mono">'+esc(n.id.slice(0,8))+'</code></div>'+
|
|
568
|
+
'<div style="font-size:0.85rem;margin-bottom:6px">'+esc(n.fullContent||n.label)+'</div>'+
|
|
569
|
+
'<div style="font-size:0.75rem;color:var(--muted)">Tier: '+(n.tier||'archival')+'</div>'
|
|
570
|
+
);
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
document.addEventListener('click',function(e){
|
|
574
|
+
if(e.target.tagName!=='circle'&&!tooltip.contains(e.target)) tooltip.style.display='none';
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function redrawGraph(){
|
|
579
|
+
var svg=$('graph-svg');
|
|
580
|
+
var html='';
|
|
581
|
+
for(var i=0;i<graphEdges.length;i++){
|
|
582
|
+
var ea=graphNodeMap[graphEdges[i].from],eb=graphNodeMap[graphEdges[i].to];
|
|
583
|
+
if(!ea||!eb) continue;
|
|
584
|
+
var mx=(ea.x+eb.x)/2,my=(ea.y+eb.y)/2;
|
|
585
|
+
html+='<line x1="'+ea.x+'" y1="'+ea.y+'" x2="'+eb.x+'" y2="'+eb.y+'" stroke="#30363d" stroke-width="'+(1+graphEdges[i].strength*2)+'"/>';
|
|
586
|
+
if(graphEdges[i].type) html+='<text x="'+mx+'" y="'+(my-4)+'" fill="#8b949e" font-size="9" text-anchor="middle">'+esc(graphEdges[i].type)+'</text>';
|
|
587
|
+
}
|
|
588
|
+
for(var i=0;i<graphNodes.length;i++){
|
|
589
|
+
var color=TYPE_COLORS[graphNodes[i].type]||'#8b949e';
|
|
590
|
+
html+='<circle data-nid="'+esc(graphNodes[i].id)+'" cx="'+graphNodes[i].x+'" cy="'+graphNodes[i].y+'" r="8" fill="'+color+'" stroke="#0d1117" stroke-width="2"/>';
|
|
591
|
+
html+='<text x="'+graphNodes[i].x+'" y="'+(graphNodes[i].y+20)+'" fill="'+color+'" font-size="10" text-anchor="middle" font-family="-apple-system,sans-serif">'+esc(graphNodes[i].label.slice(0,24))+'</text>';
|
|
592
|
+
}
|
|
593
|
+
setHTML(svg,html);
|
|
594
|
+
}
|
|
595
|
+
|
|
421
596
|
// -- Init --
|
|
597
|
+
makeGraphInteractive();
|
|
422
598
|
loadAll();
|
|
423
599
|
setInterval(loadAll,30000);
|
|
424
600
|
})();
|
|
@@ -513,7 +689,9 @@ function handleGraph(db, res) {
|
|
|
513
689
|
const nodes = memories.map((m) => ({
|
|
514
690
|
id: m.id,
|
|
515
691
|
label: m.content.length > 40 ? m.content.slice(0, 40) + "..." : m.content,
|
|
692
|
+
fullContent: m.content,
|
|
516
693
|
type: m.type,
|
|
694
|
+
tier: m.tier,
|
|
517
695
|
}));
|
|
518
696
|
const memoryIds = new Set(memories.map((m) => m.id));
|
|
519
697
|
const edges = relations
|
|
@@ -553,6 +731,35 @@ function handleLog(db, res, query) {
|
|
|
553
731
|
sessionId: e.sessionId,
|
|
554
732
|
})));
|
|
555
733
|
}
|
|
734
|
+
function handleActionTier(db, res, query) {
|
|
735
|
+
const id = query.id;
|
|
736
|
+
const tier = query.tier;
|
|
737
|
+
if (!id || !tier) {
|
|
738
|
+
errorResponse(res, "Missing id or tier parameter", 400);
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
const fullId = db.resolveId(id);
|
|
742
|
+
if (!fullId) {
|
|
743
|
+
errorResponse(res, `Memory "${id}" not found`, 404);
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
db.updateTier(fullId, tier);
|
|
747
|
+
jsonResponse(res, { ok: true, id: fullId, tier });
|
|
748
|
+
}
|
|
749
|
+
function handleActionExpire(db, res, query) {
|
|
750
|
+
const id = query.id;
|
|
751
|
+
if (!id) {
|
|
752
|
+
errorResponse(res, "Missing id parameter", 400);
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
const fullId = db.resolveId(id);
|
|
756
|
+
if (!fullId) {
|
|
757
|
+
errorResponse(res, `Memory "${id}" not found`, 404);
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
db.expireMemory(fullId);
|
|
761
|
+
jsonResponse(res, { ok: true, id: fullId, expired: true });
|
|
762
|
+
}
|
|
556
763
|
function handleSummaries(db, res, query) {
|
|
557
764
|
const limit = Math.min(50, Math.max(1, parseInt(query.limit || "10", 10) || 10));
|
|
558
765
|
const project = query.project || "global";
|
|
@@ -598,6 +805,12 @@ export function startDashboard(db, port) {
|
|
|
598
805
|
case "/api/summaries":
|
|
599
806
|
handleSummaries(db, res, query);
|
|
600
807
|
break;
|
|
808
|
+
case "/api/action/tier":
|
|
809
|
+
handleActionTier(db, res, query);
|
|
810
|
+
break;
|
|
811
|
+
case "/api/action/expire":
|
|
812
|
+
handleActionExpire(db, res, query);
|
|
813
|
+
break;
|
|
601
814
|
default:
|
|
602
815
|
errorResponse(res, "Not found", 404);
|
|
603
816
|
}
|
package/dist/dashboard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,8EAA8E;AAC9E,0DAA0D;AAC1D,sEAAsE;AACtE,sEAAsE;AACtE,8EAA8E;AAE9E,MAAM,cAAc,GAAG
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"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"}
|