engram-mcp-server 1.7.3 → 1.9.0
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 +109 -87
- package/dist/constants.d.ts +16 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +19 -2
- package/dist/constants.js.map +1 -1
- package/dist/database.d.ts +5 -2
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +41 -11
- package/dist/database.js.map +1 -1
- package/dist/http-auth.d.ts +11 -0
- package/dist/http-auth.d.ts.map +1 -0
- package/dist/http-auth.js +50 -0
- package/dist/http-auth.js.map +1 -0
- package/dist/http-pagination.d.ts +26 -0
- package/dist/http-pagination.d.ts.map +1 -0
- package/dist/http-pagination.js +43 -0
- package/dist/http-pagination.js.map +1 -0
- package/dist/http-routes/analytics.routes.d.ts +2 -0
- package/dist/http-routes/analytics.routes.d.ts.map +1 -0
- package/dist/http-routes/analytics.routes.js +64 -0
- package/dist/http-routes/analytics.routes.js.map +1 -0
- package/dist/http-routes/annotations.routes.d.ts +2 -0
- package/dist/http-routes/annotations.routes.d.ts.map +1 -0
- package/dist/http-routes/annotations.routes.js +74 -0
- package/dist/http-routes/annotations.routes.js.map +1 -0
- package/dist/http-routes/api-helpers.d.ts +19 -0
- package/dist/http-routes/api-helpers.d.ts.map +1 -0
- package/dist/http-routes/api-helpers.js +24 -0
- package/dist/http-routes/api-helpers.js.map +1 -0
- package/dist/http-routes/audit.routes.d.ts +2 -0
- package/dist/http-routes/audit.routes.d.ts.map +1 -0
- package/dist/http-routes/audit.routes.js +31 -0
- package/dist/http-routes/audit.routes.js.map +1 -0
- package/dist/http-routes/changes.routes.d.ts +2 -0
- package/dist/http-routes/changes.routes.d.ts.map +1 -0
- package/dist/http-routes/changes.routes.js +27 -0
- package/dist/http-routes/changes.routes.js.map +1 -0
- package/dist/http-routes/conventions.routes.d.ts +2 -0
- package/dist/http-routes/conventions.routes.d.ts.map +1 -0
- package/dist/http-routes/conventions.routes.js +68 -0
- package/dist/http-routes/conventions.routes.js.map +1 -0
- package/dist/http-routes/decisions.routes.d.ts +2 -0
- package/dist/http-routes/decisions.routes.d.ts.map +1 -0
- package/dist/http-routes/decisions.routes.js +86 -0
- package/dist/http-routes/decisions.routes.js.map +1 -0
- package/dist/http-routes/events.routes.d.ts +2 -0
- package/dist/http-routes/events.routes.d.ts.map +1 -0
- package/dist/http-routes/events.routes.js +20 -0
- package/dist/http-routes/events.routes.js.map +1 -0
- package/dist/http-routes/export-import.routes.d.ts +2 -0
- package/dist/http-routes/export-import.routes.d.ts.map +1 -0
- package/dist/http-routes/export-import.routes.js +46 -0
- package/dist/http-routes/export-import.routes.js.map +1 -0
- package/dist/http-routes/file-notes.routes.d.ts +2 -0
- package/dist/http-routes/file-notes.routes.d.ts.map +1 -0
- package/dist/http-routes/file-notes.routes.js +62 -0
- package/dist/http-routes/file-notes.routes.js.map +1 -0
- package/dist/http-routes/instances.routes.d.ts +2 -0
- package/dist/http-routes/instances.routes.d.ts.map +1 -0
- package/dist/http-routes/instances.routes.js +16 -0
- package/dist/http-routes/instances.routes.js.map +1 -0
- package/dist/http-routes/milestones.routes.d.ts +2 -0
- package/dist/http-routes/milestones.routes.d.ts.map +1 -0
- package/dist/http-routes/milestones.routes.js +54 -0
- package/dist/http-routes/milestones.routes.js.map +1 -0
- package/dist/http-routes/search.routes.d.ts +2 -0
- package/dist/http-routes/search.routes.d.ts.map +1 -0
- package/dist/http-routes/search.routes.js +41 -0
- package/dist/http-routes/search.routes.js.map +1 -0
- package/dist/http-routes/sensitive.routes.d.ts +2 -0
- package/dist/http-routes/sensitive.routes.d.ts.map +1 -0
- package/dist/http-routes/sensitive.routes.js +20 -0
- package/dist/http-routes/sensitive.routes.js.map +1 -0
- package/dist/http-routes/sessions.routes.d.ts +2 -0
- package/dist/http-routes/sessions.routes.d.ts.map +1 -0
- package/dist/http-routes/sessions.routes.js +51 -0
- package/dist/http-routes/sessions.routes.js.map +1 -0
- package/dist/http-routes/settings.routes.d.ts +2 -0
- package/dist/http-routes/settings.routes.d.ts.map +1 -0
- package/dist/http-routes/settings.routes.js +51 -0
- package/dist/http-routes/settings.routes.js.map +1 -0
- package/dist/http-routes/tasks.routes.d.ts +2 -0
- package/dist/http-routes/tasks.routes.d.ts.map +1 -0
- package/dist/http-routes/tasks.routes.js +90 -0
- package/dist/http-routes/tasks.routes.js.map +1 -0
- package/dist/http-server.d.ts +14 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +129 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.js +133 -4
- package/dist/index.js.map +1 -1
- package/dist/installer/config-writer.d.ts +7 -2
- package/dist/installer/config-writer.d.ts.map +1 -1
- package/dist/installer/config-writer.js +14 -3
- package/dist/installer/config-writer.js.map +1 -1
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +30 -22
- package/dist/installer/index.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +119 -0
- package/dist/migrations.js.map +1 -1
- package/dist/services/cross-instance.service.d.ts +119 -0
- package/dist/services/cross-instance.service.d.ts.map +1 -0
- package/dist/services/cross-instance.service.js +399 -0
- package/dist/services/cross-instance.service.js.map +1 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +3 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/instance-registry.service.d.ts +73 -0
- package/dist/services/instance-registry.service.d.ts.map +1 -0
- package/dist/services/instance-registry.service.js +365 -0
- package/dist/services/instance-registry.service.js.map +1 -0
- package/dist/services/sensitive-data.service.d.ts +87 -0
- package/dist/services/sensitive-data.service.d.ts.map +1 -0
- package/dist/services/sensitive-data.service.js +215 -0
- package/dist/services/sensitive-data.service.js.map +1 -0
- package/dist/tools/dispatcher-admin.d.ts.map +1 -1
- package/dist/tools/dispatcher-admin.js +290 -1
- package/dist/tools/dispatcher-admin.js.map +1 -1
- package/dist/tools/find.d.ts.map +1 -1
- package/dist/tools/find.js +16 -0
- package/dist/tools/find.js.map +1 -1
- package/dist/types.d.ts +51 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +16 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +79 -2
- package/dist/utils.js.map +1 -1
- package/dist/ws-broadcaster.d.ts +18 -0
- package/dist/ws-broadcaster.d.ts.map +1 -0
- package/dist/ws-broadcaster.js +39 -0
- package/dist/ws-broadcaster.js.map +1 -0
- package/package.json +38 -5
package/README.md
CHANGED
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
+
> ⭐ **If Engram saves you tokens and context, give it a star — it helps other developers find it.**
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
21
25
|
## 📋 Table of Contents
|
|
22
26
|
|
|
23
27
|
- [Overview](#overview)
|
|
@@ -25,12 +29,14 @@
|
|
|
25
29
|
- [How Engram Works?](#how-engram-works)
|
|
26
30
|
- [Installation](#installation)
|
|
27
31
|
- [Features](#features)
|
|
32
|
+
- [Dashboard](#dashboard)
|
|
28
33
|
- [Architecture](#architecture)
|
|
29
34
|
- [Tools Reference](#tools-reference)
|
|
30
|
-
- [
|
|
35
|
+
- [AI Agent Instructions](#ai-agent-instructions)
|
|
31
36
|
- [Multi-Agent Workflows](#multi-agent-workflows)
|
|
32
37
|
- [Contributing](#contributing)
|
|
33
38
|
- [Security](#security)
|
|
39
|
+
- [Author](#author)
|
|
34
40
|
- [License](#license)
|
|
35
41
|
|
|
36
42
|
---
|
|
@@ -39,7 +45,7 @@
|
|
|
39
45
|
|
|
40
46
|
**Engram** is an [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that gives AI coding agents persistent memory across sessions. Instead of re-reading files, re-discovering architecture, and re-learning conventions every time a session starts, the agent calls `engram_session(action:"start")` and instantly receives everything it needs.
|
|
41
47
|
|
|
42
|
-
It operates seamlessly as a background brain for popular AI tools like **Claude Code**, **Claude Desktop**, **Cursor**, **Windsurf**, **Cline**, **Trae IDE**, and **GitHub Copilot** (VS Code & Visual Studio).
|
|
48
|
+
It operates seamlessly as a background brain for popular AI tools like **Claude Code**, **Claude Desktop**, **Cursor**, **Windsurf**, **Cline**, **Trae IDE**, **Antigravity IDE**, and **GitHub Copilot** (VS Code & Visual Studio).
|
|
43
49
|
|
|
44
50
|
---
|
|
45
51
|
|
|
@@ -55,6 +61,17 @@ Every AI coding agent is **stateless by default**. Each new session starts from
|
|
|
55
61
|
|
|
56
62
|
Engram solves this by providing a **persistent brain** using a native SQLite (WAL mode) database. An AI agent should only need to deeply review a file once. When you ask it to change something, it should already know where to go.
|
|
57
63
|
|
|
64
|
+
### How Engram Compares
|
|
65
|
+
|
|
66
|
+
| Tool | Approach | Local / No cloud | MCP native | Multi-agent | Works today |
|
|
67
|
+
|------|----------|:---:|:---:|:---:|:---:|
|
|
68
|
+
| **Engram** | Structured SQLite memory | ✅ | ✅ | ✅ | ✅ |
|
|
69
|
+
| mem0 | Cloud vector DB | ❌ | ⚠️ wrapper | ⚠️ | ✅ |
|
|
70
|
+
| MemGPT / Letta | In-context manipulation | ✅ | ❌ | ❌ | ✅ |
|
|
71
|
+
| Plain `CLAUDE.md` | Static text file | ✅ | ✅ | ❌ | ✅ |
|
|
72
|
+
|
|
73
|
+
Engram is the only solution that is **local-first, MCP-native, multi-agent-ready, and structured** (queryable, rankable, exportable) — not just a text file appended to every prompt.
|
|
74
|
+
|
|
58
75
|
---
|
|
59
76
|
|
|
60
77
|
## How Engram Works?
|
|
@@ -177,6 +194,8 @@ npm install -g engram-mcp-server
|
|
|
177
194
|
engram install --ide <your-ide>
|
|
178
195
|
```
|
|
179
196
|
|
|
197
|
+
Available `--ide` values: `claudecode`, `claudedesktop`, `vscode`, `cursor`, `windsurf`, `antigravity`, `visualstudio`, `cline`, `trae`, `jetbrains`
|
|
198
|
+
|
|
180
199
|
> **Note:** During install you may see `npm warn deprecated prebuild-install@7.1.3`. This is a cosmetic warning from a transitive dependency used to download SQLite prebuilt binaries. It does not affect functionality and is safe to ignore.
|
|
181
200
|
|
|
182
201
|
### Option 3: Universal Mode — Built-In Single-Tool Mode (v1.7+)
|
|
@@ -510,6 +529,60 @@ No cloud. No telemetry. No authentication surface. Memory lives in a local SQLit
|
|
|
510
529
|
|
|
511
530
|
---
|
|
512
531
|
|
|
532
|
+
## Dashboard
|
|
533
|
+
|
|
534
|
+
Engram ships with a built-in **visual dashboard** — a React SPA that gives you a live window into your agent's memory without touching the CLI.
|
|
535
|
+
|
|
536
|
+
### Starting the Dashboard
|
|
537
|
+
|
|
538
|
+
```bash
|
|
539
|
+
npm run dashboard
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
This builds the server, installs dashboard dependencies, and starts both the API and the Vite dev server concurrently. The terminal prints the full URL including the auth token:
|
|
543
|
+
|
|
544
|
+
```
|
|
545
|
+
[api] Engram HTTP server running on port 7432
|
|
546
|
+
[ui] VITE ready in 320ms
|
|
547
|
+
|
|
548
|
+
➜ Local: http://localhost:5173?token=<token>
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
Open the printed URL directly — the token is embedded in the link and required for access.
|
|
552
|
+
|
|
553
|
+
> **Security note:** The dashboard is intended for local development. The token prevents other local processes from reading your memory data. Do not expose ports `5173` or `7432` to a network.
|
|
554
|
+
|
|
555
|
+
### Pages
|
|
556
|
+
|
|
557
|
+
| Page | Description |
|
|
558
|
+
|------|-------------|
|
|
559
|
+
| **Dashboard** | Overview — session count, task totals, decisions, and change volume at a glance. Clickable stat cards navigate to the relevant page. Instance cards show per-database stats with expand/collapse. Activity chart displays recent change volume. |
|
|
560
|
+
| **Tasks** | All persistent work items with status, priority, and tags. |
|
|
561
|
+
| **Decisions** | Architectural decisions with rationale, affected files, and dependency chains. |
|
|
562
|
+
| **Changes** | Full change history — every file edit recorded by agents and git hooks. |
|
|
563
|
+
| **Conventions** | Project standards enforced every session. |
|
|
564
|
+
| **File Notes** | Agent-generated file intelligence — purpose, layer, complexity, and executive summary. |
|
|
565
|
+
| **Sessions** | Past session summaries with agent names and timestamps. |
|
|
566
|
+
| **Events** | Scheduled and triggered events, including context-pressure warnings. |
|
|
567
|
+
| **Milestones** | Named project milestones. |
|
|
568
|
+
| **Audit** | Raw event log for debugging and auditing. |
|
|
569
|
+
| **Settings** | Runtime config management — view and update config keys live. |
|
|
570
|
+
|
|
571
|
+
### Dashboard Features
|
|
572
|
+
|
|
573
|
+
- **Live updates** — WebSocket connection delivers real-time pushes when any memory record changes. A live badge in the header shows connection status.
|
|
574
|
+
- **Cmd+K palette** — keyboard-driven quick navigation to any page.
|
|
575
|
+
- **Theme toggle** — dark/light mode, persisted to `localStorage`.
|
|
576
|
+
- **Toast notifications** — non-blocking feedback for actions and live events.
|
|
577
|
+
- **Detail panel** — click any table row to expand full content in a side panel.
|
|
578
|
+
- **Token auth** — every HTTP request and WebSocket connection is validated against the `?token=<value>` query parameter.
|
|
579
|
+
|
|
580
|
+
### Requirements
|
|
581
|
+
|
|
582
|
+
The dashboard is included in the package but its frontend dependencies are installed on first run. Node.js v18+ and an internet connection for the initial `npm install` are required. Subsequent runs use the cached install.
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
513
586
|
## Architecture
|
|
514
587
|
|
|
515
588
|
```mermaid
|
|
@@ -625,111 +698,54 @@ Engram v1.7.0 exposes **4 dispatcher tools** (or 1 tool in `--mode=universal`).
|
|
|
625
698
|
|
|
626
699
|
---
|
|
627
700
|
|
|
628
|
-
##
|
|
629
|
-
|
|
630
|
-
> **Copy-paste ready.** Copy everything between the `<!-- ENGRAM_INSTRUCTIONS_START -->` and `<!-- ENGRAM_INSTRUCTIONS_END -->` markers below directly into your agent's instruction file — `CLAUDE.md`, `.github/copilot-instructions.md`, Cursor Rules, or equivalent. No reformatting needed. Works as-is.
|
|
631
|
-
|
|
632
|
-
<!-- ENGRAM_INSTRUCTIONS_START -->
|
|
633
|
-
|
|
634
|
-
## Engram — Session Rules
|
|
701
|
+
## AI Agent Instructions
|
|
635
702
|
|
|
636
|
-
**
|
|
637
|
-
Unknown action? → `engram_find({ query: "what I want to do" })`
|
|
638
|
-
Universal mode? All actions route through a single `engram` tool — call `engram({ action: "start" })` etc.
|
|
639
|
-
|
|
640
|
-
Follow these rules **every session, every project**.
|
|
641
|
-
|
|
642
|
-
> ⚠️ **MANDATORY: Call this at the start of EVERY new chat — no exceptions.**
|
|
643
|
-
> Without it, the agent is stateless. All prior context (decisions, file notes, tasks, conventions) will be invisible.
|
|
644
|
-
|
|
645
|
-
---
|
|
703
|
+
> **Important:** AI agents have a strong tendency to skip Engram tool calls — particularly `engram_session(action:"start")` at the beginning of a chat and `engram_memory(action:"get_file_notes")` before opening files — and proceed directly to reading and reviewing. This defeats the purpose of the memory system entirely. **For any session that involves file exploration or codebase work, explicitly instruct the agent in your prompt to use Engram before acting.** A simple addition like *"Before doing anything, start an Engram session. Before opening any file, check its Engram notes first."* is sufficient to enforce compliance.
|
|
646
704
|
|
|
647
|
-
|
|
705
|
+
> **Copy-paste ready.** The block below can be dropped directly into `CLAUDE.md`, `.github/copilot-instructions.md`, Cursor Rules, or any equivalent agent instruction file — no reformatting needed.
|
|
648
706
|
|
|
649
|
-
|
|
650
|
-
engram_session({
|
|
651
|
-
action: "start",
|
|
652
|
-
agent_name: "claude",
|
|
653
|
-
verbosity: "summary",
|
|
654
|
-
focus: "topic if known",
|
|
655
|
-
});
|
|
656
|
-
```
|
|
657
|
-
|
|
658
|
-
- **Every new chat. Every time. No skipping.** Even for "quick" questions — context is loaded in <1 second.
|
|
659
|
-
- Use `verbosity: "summary"` always. Never `"full"`.
|
|
660
|
-
- Act on everything returned: `previous_session`, `active_decisions` (binding), `active_conventions` (enforce), `open_tasks`, `abandoned_work`, `agent_rules` (binding), `triggered_events`.
|
|
661
|
-
- If `update_available`: ask user → update (`npx -y engram-mcp-server install`), skip, postpone 7d, or disable.
|
|
662
|
-
|
|
663
|
-
---
|
|
664
|
-
|
|
665
|
-
### Before Opening a File
|
|
707
|
+
<!-- ENGRAM_INSTRUCTIONS_START -->
|
|
666
708
|
|
|
709
|
+
### Session Start — ALWAYS FIRST
|
|
667
710
|
```js
|
|
668
|
-
|
|
711
|
+
engram_session({ action: "start", agent_name: "claude", verbosity: "summary", focus: "topic if known" })
|
|
669
712
|
```
|
|
713
|
+
Act on everything returned: `active_decisions` (binding), `active_conventions` (enforce), `open_tasks`, `agent_rules`, `triggered_events`.
|
|
714
|
+
Unknown action? → `engram_find({ query: "what I want to do" })`
|
|
670
715
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
---
|
|
674
|
-
|
|
675
|
-
### Before Design/Architecture Decisions
|
|
676
|
-
|
|
716
|
+
### Before Opening Any File
|
|
677
717
|
```js
|
|
678
|
-
engram_memory({ action: "
|
|
679
|
-
// or: engram_memory({ action: "get_decisions" })
|
|
718
|
+
engram_memory({ action: "get_file_notes", file_path: "..." })
|
|
680
719
|
```
|
|
720
|
+
`high` confidence → use notes, skip opening. `stale`/absent → read file, then immediately call `set_file_notes` with `executive_summary`.
|
|
681
721
|
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
---
|
|
685
|
-
|
|
686
|
-
### After Editing Files
|
|
687
|
-
|
|
722
|
+
### Before Architecture/Design Decisions
|
|
688
723
|
```js
|
|
689
|
-
engram_memory({
|
|
690
|
-
action: "record_change",
|
|
691
|
-
changes: [{ file_path, change_type, description, impact_scope }],
|
|
692
|
-
});
|
|
724
|
+
engram_memory({ action: "search", query: "...", scope: "decisions" })
|
|
693
725
|
```
|
|
726
|
+
Follow existing decisions. Supersede with `record_decision({ ..., supersedes: <id> })`. Always include `rationale`.
|
|
694
727
|
|
|
695
|
-
|
|
696
|
-
`impact_scope`: local | module | cross_module | global. Batch all changes in one call.
|
|
697
|
-
|
|
698
|
-
---
|
|
699
|
-
|
|
700
|
-
### Mid-Session (context pressure)
|
|
701
|
-
|
|
728
|
+
### After Every File Edit
|
|
702
729
|
```js
|
|
703
|
-
engram_memory({ action: "
|
|
704
|
-
engram_memory({ action: "check_events" }) // fires at 50/70/85% context fill
|
|
730
|
+
engram_memory({ action: "record_change", changes: [{ file_path, change_type, description, impact_scope }] })
|
|
705
731
|
```
|
|
732
|
+
`change_type`: `created|modified|refactored|deleted|renamed|moved|config_changed`
|
|
733
|
+
`impact_scope`: `local|module|cross_module|global` — batch all edits in one call.
|
|
706
734
|
|
|
707
|
-
|
|
735
|
+
### Documentation Rule
|
|
736
|
+
Multi-step plans, analyses, proposals → write to `docs/<name>.md`. Chat gets summary only.
|
|
708
737
|
|
|
709
738
|
### Session End — ALWAYS LAST
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
4. Record new conventions.
|
|
715
|
-
5. `engram_session({ action: "end", summary: "files/functions touched, pending work, blockers" })`
|
|
716
|
-
|
|
717
|
-
---
|
|
739
|
+
1. Record unrecorded changes
|
|
740
|
+
2. Mark done tasks: `engram_memory({ action: "update_task", id: N, status: "done" })`
|
|
741
|
+
3. Create tasks for incomplete work
|
|
742
|
+
4. `engram_session({ action: "end", summary: "files touched, pending work, blockers" })`
|
|
718
743
|
|
|
719
744
|
### Sub-Agent Sessions (v1.7+)
|
|
720
|
-
|
|
721
|
-
Use `agent_role: "sub"` for lightweight task-scoped context (~300–500 tokens):
|
|
722
|
-
|
|
723
745
|
```js
|
|
724
|
-
engram_session({
|
|
725
|
-
action: "start",
|
|
726
|
-
agent_name: "sub-agent-auth",
|
|
727
|
-
agent_role: "sub",
|
|
728
|
-
task_id: 42,
|
|
729
|
-
});
|
|
746
|
+
engram_session({ action: "start", agent_name: "sub-agent-X", agent_role: "sub", task_id: 42 })
|
|
730
747
|
```
|
|
731
|
-
|
|
732
|
-
Returns only: the assigned task, its file notes, matching decisions, and up to 5 relevant conventions. Sub-agents still call `record_change` and `session end` as normal.
|
|
748
|
+
Returns only the assigned task, its file notes, matching decisions, and up to 5 conventions (~300–500 tokens). Sub-agents still call `record_change` and `session end` as normal.
|
|
733
749
|
|
|
734
750
|
<!-- ENGRAM_INSTRUCTIONS_END -->
|
|
735
751
|
|
|
@@ -946,15 +962,21 @@ The short version: Engram has no network-facing server, no authentication surfac
|
|
|
946
962
|
|
|
947
963
|
---
|
|
948
964
|
|
|
965
|
+
## Author
|
|
966
|
+
|
|
967
|
+
Built by **Renald Shao** (aka **Keggan Student**) — [GitHub](https://github.com/keggan-std) · [Behance](https://www.behance.net/renaldshao)
|
|
968
|
+
|
|
969
|
+
---
|
|
970
|
+
|
|
949
971
|
## License
|
|
950
972
|
|
|
951
973
|
This project is licensed under the [MIT License](LICENSE).
|
|
952
974
|
|
|
953
|
-
Copyright © 2026 Keggan Student, Tanzania.
|
|
975
|
+
Copyright © 2026 Renald Shao (aka Keggan Student), Tanzania.
|
|
954
976
|
|
|
955
977
|
---
|
|
956
978
|
|
|
957
979
|
<div align="center">
|
|
958
980
|
<em>Because your AI agent shouldn't have amnesia.</em><br/>
|
|
959
|
-
<strong>Copyright © 2026 Keggan Student — Tanzania</strong>
|
|
981
|
+
<strong>Copyright © 2026 Renald Shao (aka Keggan Student) — Tanzania</strong>
|
|
960
982
|
</div>
|
package/dist/constants.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export declare const SERVER_VERSION: string;
|
|
|
3
3
|
export declare const TOOL_PREFIX = "engram";
|
|
4
4
|
export declare const DB_DIR_NAME = ".engram";
|
|
5
5
|
export declare const DB_FILE_NAME = "memory.db";
|
|
6
|
-
export declare const DB_VERSION =
|
|
6
|
+
export declare const DB_VERSION = 22;
|
|
7
7
|
export declare const MAX_FILE_TREE_DEPTH = 5;
|
|
8
8
|
export declare const MAX_FILE_TREE_ENTRIES = 500;
|
|
9
9
|
export declare const MAX_SEARCH_RESULTS = 50;
|
|
@@ -53,5 +53,20 @@ export declare const CFG_AUTO_UPDATE_CHANGELOG = "auto_update_changelog";
|
|
|
53
53
|
export declare const CFG_AUTO_UPDATE_SKIP_VERSION = "auto_update_skip_version";
|
|
54
54
|
export declare const CFG_AUTO_UPDATE_REMIND_AFTER = "auto_update_remind_after";
|
|
55
55
|
export declare const CFG_AUTO_UPDATE_NOTIFY_LEVEL = "auto_update_notify_level";
|
|
56
|
+
export declare const CFG_INSTANCE_ID = "instance_id";
|
|
57
|
+
export declare const CFG_INSTANCE_LABEL = "instance_label";
|
|
58
|
+
export declare const CFG_INSTANCE_CREATED_AT = "instance_created_at";
|
|
59
|
+
export declare const CFG_MACHINE_ID = "machine_id";
|
|
60
|
+
export declare const CFG_SHARING_MODE = "sharing_mode";
|
|
61
|
+
export declare const CFG_SHARING_TYPES = "sharing_types";
|
|
62
|
+
export declare const CFG_SENSITIVE_KEYS = "sensitive_keys";
|
|
63
|
+
export declare const CFG_HTTP_TOKEN = "http_token";
|
|
64
|
+
export declare const INSTANCE_REGISTRY_DIR = ".engram";
|
|
65
|
+
export declare const INSTANCE_REGISTRY_FILE = "instances.json";
|
|
66
|
+
export declare const HEARTBEAT_INTERVAL_MS = 60000;
|
|
67
|
+
export declare const STALE_THRESHOLD_MS: number;
|
|
68
|
+
export declare const PRUNE_THRESHOLD_MS: number;
|
|
69
|
+
export declare const DEFAULT_SHARING_MODE = "none";
|
|
70
|
+
export declare const DEFAULT_SHARING_TYPES: string[];
|
|
56
71
|
export declare const LAYER_PATTERNS: Record<string, RegExp[]>;
|
|
57
72
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAC/C,eAAO,MAAM,cAAc,EAAE,MAAqB,CAAC;AACnD,eAAO,MAAM,WAAW,WAAW,CAAC;AAGpC,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,eAAO,MAAM,YAAY,cAAc,CAAC;AACxC,eAAO,MAAM,UAAU,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAC/C,eAAO,MAAM,cAAc,EAAE,MAAqB,CAAC;AACnD,eAAO,MAAM,WAAW,WAAW,CAAC;AAGpC,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,eAAO,MAAM,YAAY,cAAc,CAAC;AACxC,eAAO,MAAM,UAAU,KAAK,CAAC;AAG7B,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AACzC,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,eAAe,YAAY,CAAC;AACzC,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,iCAAiC,KAAK,CAAC;AACpD,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAGnC,eAAO,MAAM,aAAa,aAqBxB,CAAC;AAKH;;;GAGG;AACH,eAAO,MAAM,sBAAsB,8BAGzB,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,UAkBhC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,UAG3B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,EAmBzC,CAAC;AAGF,eAAO,MAAM,gBAAgB,wDAAwD,CAAC;AACtF,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAC/C,eAAO,MAAM,mBAAmB,kDAAkD,CAAC;AACnF,eAAO,MAAM,uBAAuB,mEAAmE,CAAC;AAGxG,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AACzD,eAAO,MAAM,0BAA0B,2BAA2B,CAAC;AACnE,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AACjE,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AACjE,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AACvE,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AACvE,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AAGvE,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAC7C,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAC7D,eAAO,MAAM,cAAc,eAAe,CAAC;AAC3C,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAC/C,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AACjD,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,cAAc,eAAe,CAAC;AAG3C,eAAO,MAAM,qBAAqB,YAAY,CAAC;AAC/C,eAAO,MAAM,sBAAsB,mBAAmB,CAAC;AACvD,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAC5C,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAC7C,eAAO,MAAM,kBAAkB,QAAuB,CAAC;AAGvD,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAC3C,eAAO,MAAM,qBAAqB,UAA+B,CAAC;AAGlE,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAYnD,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -12,8 +12,7 @@ export const TOOL_PREFIX = "engram";
|
|
|
12
12
|
// Database
|
|
13
13
|
export const DB_DIR_NAME = ".engram";
|
|
14
14
|
export const DB_FILE_NAME = "memory.db";
|
|
15
|
-
export const DB_VERSION =
|
|
16
|
-
// V12 checkpoints, V13 content_hash, V14 executive_summary, V15 agent specializations
|
|
15
|
+
export const DB_VERSION = 22; // V18 http-token, V19 soft-delete, V20 audit-log, V21 import-jobs, V22 annotations
|
|
17
16
|
// Limits
|
|
18
17
|
export const MAX_FILE_TREE_DEPTH = 5;
|
|
19
18
|
export const MAX_FILE_TREE_ENTRIES = 500;
|
|
@@ -133,6 +132,24 @@ export const CFG_AUTO_UPDATE_CHANGELOG = "auto_update_changelog";
|
|
|
133
132
|
export const CFG_AUTO_UPDATE_SKIP_VERSION = "auto_update_skip_version";
|
|
134
133
|
export const CFG_AUTO_UPDATE_REMIND_AFTER = "auto_update_remind_after";
|
|
135
134
|
export const CFG_AUTO_UPDATE_NOTIFY_LEVEL = "auto_update_notify_level"; // "major" | "minor" | "patch"
|
|
135
|
+
// Config keys — instance identity & cross-instance
|
|
136
|
+
export const CFG_INSTANCE_ID = "instance_id";
|
|
137
|
+
export const CFG_INSTANCE_LABEL = "instance_label";
|
|
138
|
+
export const CFG_INSTANCE_CREATED_AT = "instance_created_at";
|
|
139
|
+
export const CFG_MACHINE_ID = "machine_id";
|
|
140
|
+
export const CFG_SHARING_MODE = "sharing_mode"; // "none" | "read" | "full"
|
|
141
|
+
export const CFG_SHARING_TYPES = "sharing_types"; // JSON array of table names
|
|
142
|
+
export const CFG_SENSITIVE_KEYS = "sensitive_keys"; // JSON array of decision/convention IDs marked sensitive
|
|
143
|
+
export const CFG_HTTP_TOKEN = "http_token"; // Bearer token for dashboard API (file fallback: .engram/token)
|
|
144
|
+
// Instance registry
|
|
145
|
+
export const INSTANCE_REGISTRY_DIR = ".engram";
|
|
146
|
+
export const INSTANCE_REGISTRY_FILE = "instances.json";
|
|
147
|
+
export const HEARTBEAT_INTERVAL_MS = 60_000; // 60 seconds
|
|
148
|
+
export const STALE_THRESHOLD_MS = 5 * 60_000; // 5 minutes
|
|
149
|
+
export const PRUNE_THRESHOLD_MS = 7 * 24 * 60 * 60_000; // 7 days
|
|
150
|
+
// Sharing defaults
|
|
151
|
+
export const DEFAULT_SHARING_MODE = "none";
|
|
152
|
+
export const DEFAULT_SHARING_TYPES = ["decisions", "conventions"];
|
|
136
153
|
// Architecture layer detection patterns
|
|
137
154
|
export const LAYER_PATTERNS = {
|
|
138
155
|
ui: [/\/(ui|views?|screens?|pages?|components?|widgets?)\//i, /\.(jsx|tsx|vue|svelte)$/],
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,gCAAgC;AAChC,+EAA+E;AAE/E,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;AAC/F,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAEzD,MAAM,CAAC,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAC/C,MAAM,CAAC,MAAM,cAAc,GAAW,IAAI,CAAC,OAAO,CAAC;AACnD,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAEpC,WAAW;AACX,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC;AACxC,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
|
package/dist/database.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Database as DatabaseType } from "better-sqlite3";
|
|
2
2
|
import { type Repositories } from "./repositories/index.js";
|
|
3
|
-
import { CompactionService, ProjectScanService, GitService, EventTriggerService, UpdateService, AgentRulesService } from "./services/index.js";
|
|
3
|
+
import { CompactionService, ProjectScanService, GitService, EventTriggerService, UpdateService, AgentRulesService, InstanceRegistryService, CrossInstanceService, SensitiveDataService } from "./services/index.js";
|
|
4
4
|
export interface Services {
|
|
5
5
|
compaction: CompactionService;
|
|
6
6
|
scan: ProjectScanService;
|
|
@@ -8,8 +8,11 @@ export interface Services {
|
|
|
8
8
|
events: EventTriggerService;
|
|
9
9
|
update: UpdateService;
|
|
10
10
|
agentRules: AgentRulesService;
|
|
11
|
+
registry: InstanceRegistryService;
|
|
12
|
+
crossInstance: CrossInstanceService;
|
|
13
|
+
sensitiveData: SensitiveDataService;
|
|
11
14
|
}
|
|
12
|
-
export declare function initDatabase(projectRoot: string): DatabaseType;
|
|
15
|
+
export declare function initDatabase(projectRoot: string, ideKey?: string): DatabaseType;
|
|
13
16
|
export declare function getDb(): DatabaseType;
|
|
14
17
|
export declare function getRepos(): Repositories;
|
|
15
18
|
export declare function getServices(): Services;
|
package/dist/database.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAK/D,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,mBAAmB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAK/D,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,mBAAmB,EAAE,aAAa,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAKpN,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,IAAI,EAAE,kBAAkB,CAAC;IACzB,GAAG,EAAE,UAAU,CAAC;IAChB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,QAAQ,EAAE,uBAAuB,CAAC;IAClC,aAAa,EAAE,oBAAoB,CAAC;IACpC,aAAa,EAAE,oBAAoB,CAAC;CACrC;AA4ED,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CA6D/E;AAED,wBAAgB,KAAK,IAAI,YAAY,CAGpC;AAED,wBAAgB,QAAQ,IAAI,YAAY,CAGvC;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAGtC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAID;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAwBxD;AAmCD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAIvF;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAK5F;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAI/E;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,GAAG,IAAI,CAQvF;AAID,wBAAgB,GAAG,IAAI,MAAM,CAE5B;AAED,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAGnD;AAED,wBAAgB,uBAAuB,IAAI;IACzC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;CAC1E,GAAG,IAAI,CAWP;AAED,wBAAgB,WAAW,IAAI,MAAM,CAKpC;AAED,wBAAgB,UAAU,IAAI,IAAI,CAIjC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,SAAS,GAAG,OAAmB,EACxC,KAAK,CAAC,EAAE,MAAM,GACb,IAAI,CAcN"}
|
package/dist/database.js
CHANGED
|
@@ -7,8 +7,10 @@ import * as path from "path";
|
|
|
7
7
|
import { DB_DIR_NAME, DB_FILE_NAME, BACKUP_DIR_NAME } from "./constants.js";
|
|
8
8
|
import { runMigrations } from "./migrations.js";
|
|
9
9
|
import { createRepositories } from "./repositories/index.js";
|
|
10
|
-
import { CompactionService, ProjectScanService, GitService, EventTriggerService, UpdateService, AgentRulesService } from "./services/index.js";
|
|
11
|
-
import { SERVER_VERSION } from "./constants.js";
|
|
10
|
+
import { CompactionService, ProjectScanService, GitService, EventTriggerService, UpdateService, AgentRulesService, InstanceRegistryService, CrossInstanceService, SensitiveDataService } from "./services/index.js";
|
|
11
|
+
import { SERVER_VERSION, CFG_INSTANCE_ID, CFG_INSTANCE_LABEL, CFG_INSTANCE_CREATED_AT, CFG_MACHINE_ID, CFG_SHARING_MODE, CFG_SHARING_TYPES, DEFAULT_SHARING_MODE, DEFAULT_SHARING_TYPES } from "./constants.js";
|
|
12
|
+
import { getMachineId, generateInstanceLabel } from "./utils.js";
|
|
13
|
+
import { randomUUID } from "crypto";
|
|
12
14
|
let _db = null;
|
|
13
15
|
let _repos = null;
|
|
14
16
|
let _services = null;
|
|
@@ -35,9 +37,8 @@ function openDatabaseWithRecovery(dbPath) {
|
|
|
35
37
|
// ── First attempt ──────────────────────────────────────────────────
|
|
36
38
|
try {
|
|
37
39
|
const db = new Database(dbPath);
|
|
38
|
-
db.pragma("busy_timeout =
|
|
39
|
-
db.pragma("journal_mode = WAL"); //
|
|
40
|
-
db.pragma("journal_mode = DELETE"); // reset so caller sets it properly
|
|
40
|
+
db.pragma("busy_timeout = 15000"); // 15 s — multi-IDE shards may still share a file
|
|
41
|
+
db.pragma("journal_mode = WAL"); // set WAL (or confirm already in WAL) — no-op if already WAL
|
|
41
42
|
return db;
|
|
42
43
|
}
|
|
43
44
|
catch (err) {
|
|
@@ -60,9 +61,8 @@ function openDatabaseWithRecovery(dbPath) {
|
|
|
60
61
|
}
|
|
61
62
|
try {
|
|
62
63
|
const db = new Database(dbPath);
|
|
63
|
-
db.pragma("busy_timeout =
|
|
64
|
+
db.pragma("busy_timeout = 15000"); // 15 s
|
|
64
65
|
db.pragma("journal_mode = WAL");
|
|
65
|
-
db.pragma("journal_mode = DELETE");
|
|
66
66
|
console.error("[Engram] [WARN] Recovered from corrupt WAL/SHM — some recent changes may be lost.");
|
|
67
67
|
return db;
|
|
68
68
|
}
|
|
@@ -78,30 +78,39 @@ function openDatabaseWithRecovery(dbPath) {
|
|
|
78
78
|
catch { /* best-effort */ }
|
|
79
79
|
console.error("[Engram] [WARN] Main database was corrupt — renamed to backup, starting fresh.");
|
|
80
80
|
const freshDb = new Database(dbPath);
|
|
81
|
-
freshDb.pragma("busy_timeout =
|
|
81
|
+
freshDb.pragma("busy_timeout = 15000"); // 15 s
|
|
82
82
|
return freshDb;
|
|
83
83
|
}
|
|
84
84
|
// FLAW-5 FIX: initDatabase is synchronous (better-sqlite3 is sync throughout).
|
|
85
85
|
// The misleading async/Promise wrapper is removed — callers no longer need
|
|
86
86
|
// to remember to await a function that never actually awaits anything.
|
|
87
|
-
|
|
87
|
+
//
|
|
88
|
+
// ideKey: when provided, the DB is opened as memory-{ideKey}.db instead of memory.db.
|
|
89
|
+
// Global-only IDEs (no workspaceVar) pass their IDE key so each IDE type gets its own
|
|
90
|
+
// shard, eliminating write-lock contention between different IDEs on the same project.
|
|
91
|
+
export function initDatabase(projectRoot, ideKey) {
|
|
88
92
|
_projectRoot = projectRoot;
|
|
89
93
|
const dbDir = path.join(projectRoot, DB_DIR_NAME);
|
|
90
94
|
fs.mkdirSync(dbDir, { recursive: true });
|
|
91
95
|
ensureGitignore(projectRoot);
|
|
92
|
-
|
|
96
|
+
// Per-IDE shard: global installs without workspaceVar use memory-{ideKey}.db
|
|
97
|
+
const dbFileName = ideKey ? `memory-${ideKey}.db` : DB_FILE_NAME;
|
|
98
|
+
_dbPath = path.join(dbDir, dbFileName);
|
|
93
99
|
_db = openDatabaseWithRecovery(_dbPath);
|
|
94
100
|
// Performance pragmas (busy_timeout already set inside openDatabaseWithRecovery)
|
|
95
101
|
_db.pragma("journal_mode = WAL");
|
|
96
102
|
_db.pragma("foreign_keys = ON");
|
|
97
103
|
_db.pragma("synchronous = NORMAL");
|
|
98
104
|
_db.pragma("cache_size = -8000"); // 8MB cache
|
|
99
|
-
_db.pragma("
|
|
105
|
+
_db.pragma("wal_autocheckpoint = 100"); // checkpoint every 100 pages for faster readers
|
|
106
|
+
_db.pragma("mmap_size = 67108864"); // 64MB memory-mapped I/O
|
|
107
|
+
_db.pragma("busy_timeout = 15000"); // 15 s — handles same-IDE multi-window contention
|
|
100
108
|
// Run versioned migrations
|
|
101
109
|
runMigrations(_db);
|
|
102
110
|
// Initialize repositories
|
|
103
111
|
_repos = createRepositories(_db);
|
|
104
112
|
// Initialize services
|
|
113
|
+
const registryService = new InstanceRegistryService(_repos.config, projectRoot, _db, dbFileName);
|
|
105
114
|
_services = {
|
|
106
115
|
compaction: new CompactionService(_db, _repos),
|
|
107
116
|
scan: new ProjectScanService(_repos),
|
|
@@ -109,7 +118,28 @@ export function initDatabase(projectRoot) {
|
|
|
109
118
|
events: new EventTriggerService(_repos),
|
|
110
119
|
update: new UpdateService(_repos, SERVER_VERSION),
|
|
111
120
|
agentRules: new AgentRulesService(projectRoot),
|
|
121
|
+
registry: registryService,
|
|
122
|
+
crossInstance: new CrossInstanceService(registryService),
|
|
123
|
+
sensitiveData: new SensitiveDataService(_repos.config, _db),
|
|
112
124
|
};
|
|
125
|
+
// ─── Instance Identity ─────────────────────────────────────────────
|
|
126
|
+
// Generate stable identity on first run after v17 migration.
|
|
127
|
+
// These values live in the config table and never change once set.
|
|
128
|
+
const existingId = _repos.config.get(CFG_INSTANCE_ID);
|
|
129
|
+
if (!existingId) {
|
|
130
|
+
const ts = now();
|
|
131
|
+
_repos.config.set(CFG_INSTANCE_ID, randomUUID(), ts);
|
|
132
|
+
_repos.config.set(CFG_INSTANCE_LABEL, generateInstanceLabel(projectRoot), ts);
|
|
133
|
+
_repos.config.set(CFG_INSTANCE_CREATED_AT, ts, ts);
|
|
134
|
+
_repos.config.set(CFG_MACHINE_ID, getMachineId(), ts);
|
|
135
|
+
_repos.config.set(CFG_SHARING_MODE, DEFAULT_SHARING_MODE, ts);
|
|
136
|
+
_repos.config.set(CFG_SHARING_TYPES, JSON.stringify(DEFAULT_SHARING_TYPES), ts);
|
|
137
|
+
}
|
|
138
|
+
// ─── Instance Registry ─────────────────────────────────────────────
|
|
139
|
+
// Register in ~/.engram/instances.json and start periodic heartbeat.
|
|
140
|
+
// The heartbeat timer is unref'd so it won't prevent Node from exiting.
|
|
141
|
+
_services.registry.register();
|
|
142
|
+
_services.registry.startHeartbeat();
|
|
113
143
|
return _db;
|
|
114
144
|
}
|
|
115
145
|
export function getDb() {
|
package/dist/database.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,yEAAyE;AACzE,+EAA+E;AAE/E,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAqB,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,mBAAmB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from "express";
|
|
2
|
+
export declare function getTokenFilePath(projectRoot: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Read the persisted token or generate + persist a new one.
|
|
5
|
+
*/
|
|
6
|
+
export declare function ensureToken(projectRoot: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Express middleware: validates Authorization: Bearer <token> header.
|
|
9
|
+
*/
|
|
10
|
+
export declare function bearerAuth(token: string): (req: Request, res: Response, next: NextFunction) => void;
|
|
11
|
+
//# sourceMappingURL=http-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-auth.d.ts","sourceRoot":"","sources":["../src/http-auth.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAM/D,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAkBvD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,IAC9B,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAQ/D"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Engram Dashboard — Bearer Token Authentication Middleware
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Token is stored in .engram/token (chmod 600 on POSIX).
|
|
5
|
+
// If not found, a new 32-byte hex token is generated on first start.
|
|
6
|
+
// ============================================================================
|
|
7
|
+
import { randomBytes } from "crypto";
|
|
8
|
+
import * as fs from "fs";
|
|
9
|
+
import * as path from "path";
|
|
10
|
+
import { DB_DIR_NAME } from "./constants.js";
|
|
11
|
+
import { log } from "./logger.js";
|
|
12
|
+
const TOKEN_FILE_NAME = "token";
|
|
13
|
+
export function getTokenFilePath(projectRoot) {
|
|
14
|
+
return path.join(projectRoot, DB_DIR_NAME, TOKEN_FILE_NAME);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Read the persisted token or generate + persist a new one.
|
|
18
|
+
*/
|
|
19
|
+
export function ensureToken(projectRoot) {
|
|
20
|
+
const tokenPath = getTokenFilePath(projectRoot);
|
|
21
|
+
if (fs.existsSync(tokenPath)) {
|
|
22
|
+
try {
|
|
23
|
+
const t = fs.readFileSync(tokenPath, "utf-8").trim();
|
|
24
|
+
if (t && t.length >= 32)
|
|
25
|
+
return t;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
/* fall through to regenerate */
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const token = randomBytes(32).toString("hex");
|
|
32
|
+
fs.mkdirSync(path.dirname(tokenPath), { recursive: true });
|
|
33
|
+
fs.writeFileSync(tokenPath, token, { encoding: "utf-8", mode: 0o600 });
|
|
34
|
+
log.info(`[Dashboard] New API token generated at ${tokenPath}`);
|
|
35
|
+
return token;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Express middleware: validates Authorization: Bearer <token> header.
|
|
39
|
+
*/
|
|
40
|
+
export function bearerAuth(token) {
|
|
41
|
+
return (req, res, next) => {
|
|
42
|
+
const auth = req.headers["authorization"] ?? "";
|
|
43
|
+
if (auth === `Bearer ${token}`) {
|
|
44
|
+
next();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
res.status(401).json({ ok: false, error: "UNAUTHORIZED", message: "Invalid or missing bearer token." });
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=http-auth.js.map
|