@cartisien/engram 0.3.0 → 0.5.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 +83 -3
- package/dist/adapters/base.d.ts +2 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +2 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/memory.d.ts +17 -0
- package/dist/adapters/memory.d.ts.map +1 -0
- package/dist/adapters/memory.js +58 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/adapters/postgres.d.ts +33 -0
- package/dist/adapters/postgres.d.ts.map +1 -0
- package/dist/adapters/postgres.js +47 -0
- package/dist/adapters/postgres.js.map +1 -0
- package/dist/adapters/sqlite.d.ts +19 -0
- package/dist/adapters/sqlite.d.ts.map +1 -0
- package/dist/adapters/sqlite.js +33 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/engram.d.ts +57 -0
- package/dist/engram.d.ts.map +1 -0
- package/dist/engram.js +148 -0
- package/dist/engram.js.map +1 -0
- package/dist/index.d.ts +126 -34
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +496 -120
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +48 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/embeddings.d.ts +20 -0
- package/dist/utils/embeddings.d.ts.map +1 -0
- package/dist/utils/embeddings.js +28 -0
- package/dist/utils/embeddings.js.map +1 -0
- package/dist/utils/similarity.d.ts +10 -0
- package/dist/utils/similarity.d.ts.map +1 -0
- package/dist/utils/similarity.js +31 -0
- package/dist/utils/similarity.js.map +1 -0
- package/package.json +3 -2
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> **Persistent semantic memory for AI agents.**
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
```typescript
|
|
6
8
|
import { Engram } from '@cartisien/engram';
|
|
7
9
|
|
|
@@ -28,6 +30,8 @@ Stuffing everything into the system prompt wastes tokens and still misses things
|
|
|
28
30
|
Engram gives your agents **persistent, semantically searchable memory** — SQLite-backed, TypeScript-first, zero config.
|
|
29
31
|
|
|
30
32
|
- **Semantic search:** Finds relevant memories by meaning, not just keywords (via local Ollama embeddings)
|
|
33
|
+
- **Graph memory:** Extracts entity-relationship triples — recall connected context automatically
|
|
34
|
+
- **Consolidation:** Summarizes old memories into long-term entries so context stays dense, not noisy
|
|
31
35
|
- **Zero config:** Works out of the box, falls back to keyword search without Ollama
|
|
32
36
|
- **Local-first:** Your data stays on your machine. No API keys, no cloud required
|
|
33
37
|
- **MCP-native:** Drop into Claude Desktop or Cursor via [`@cartisien/engram-mcp`](https://github.com/Cartisien/engram-mcp)
|
|
@@ -127,11 +131,87 @@ await memory.forget('session_abc', { id: 'entry_id' }); // one
|
|
|
127
131
|
await memory.forget('session_abc', { before: new Date() }); // old entries
|
|
128
132
|
```
|
|
129
133
|
|
|
134
|
+
### `graph(sessionId, entity)`
|
|
135
|
+
|
|
136
|
+
Returns a one-hop relationship map for a named entity — all connected entities and the memories that link them.
|
|
137
|
+
|
|
138
|
+
Requires `graphMemory: true` in config and a running Ollama instance with `qwen2.5:32b` (or override via `graphModel`).
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
const memory = new Engram({
|
|
142
|
+
dbPath: './memory.db',
|
|
143
|
+
graphMemory: true,
|
|
144
|
+
graphModel: 'qwen2.5:32b', // default
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const graph = await memory.graph('session_abc', 'GovScout');
|
|
148
|
+
// {
|
|
149
|
+
// entity: 'GovScout',
|
|
150
|
+
// edges: [
|
|
151
|
+
// { relation: 'uses', target: 'MUI', sourceMemoryId: '...' },
|
|
152
|
+
// { relation: 'built_by', target: 'Jeff', sourceMemoryId: '...' },
|
|
153
|
+
// ],
|
|
154
|
+
// memories: [ { content: '...', ... } ]
|
|
155
|
+
// }
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### `recall()` with graph augmentation
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
const results = await memory.recall('session_abc', 'what is GovScout?', 5, {
|
|
162
|
+
includeGraph: true, // augment top results with graph-connected memories
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### `consolidate(sessionId, options?)` *(v0.4)*
|
|
167
|
+
|
|
168
|
+
Summarizes old working memories into dense long-term entries via a local LLM. Originals are archived (hidden from recall but not deleted).
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const memory = new Engram({
|
|
172
|
+
dbPath: './memory.db',
|
|
173
|
+
autoConsolidate: true, // auto-trigger on remember() (default: false)
|
|
174
|
+
consolidateThreshold: 100, // trigger when working memories exceed this (default: 100)
|
|
175
|
+
consolidateKeep: 20, // keep N most recent working memories untouched (default: 20)
|
|
176
|
+
consolidateBatch: 50, // memories to process per run (default: 50)
|
|
177
|
+
consolidateModel: 'qwen2.5:32b', // LLM for summarization
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Manual consolidation
|
|
181
|
+
const result = await memory.consolidate('session_abc');
|
|
182
|
+
// → { summarized: 50, created: 4, archived: 50 }
|
|
183
|
+
|
|
184
|
+
// Preview without writing
|
|
185
|
+
const preview = await memory.consolidate('session_abc', { dryRun: true });
|
|
186
|
+
// → { summarized: 50, created: 0, archived: 0, previews: ['User prefers TypeScript...', ...] }
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Memory tiers:**
|
|
190
|
+
- `working` — recent, granular memories (default)
|
|
191
|
+
- `long_term` — LLM-generated summaries of consolidated batches
|
|
192
|
+
- `archived` — original memories after consolidation (excluded from recall)
|
|
193
|
+
|
|
194
|
+
`recall()` searches `working` and `long_term` by default. Pass `tiers` to override:
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
// Search all tiers including archived
|
|
198
|
+
const results = await memory.recall('session_abc', 'preferences', 10, {
|
|
199
|
+
tiers: ['working', 'long_term', 'archived'],
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
130
203
|
### `stats(sessionId)`
|
|
131
204
|
|
|
132
205
|
```typescript
|
|
133
206
|
const stats = await memory.stats('session_abc');
|
|
134
|
-
// {
|
|
207
|
+
// {
|
|
208
|
+
// total: 42,
|
|
209
|
+
// byRole: { user: 21, assistant: 21 },
|
|
210
|
+
// byTier: { working: 30, long_term: 12, archived: 50 },
|
|
211
|
+
// withEmbeddings: 42,
|
|
212
|
+
// graphNodes: 18,
|
|
213
|
+
// graphEdges: 31
|
|
214
|
+
// }
|
|
135
215
|
```
|
|
136
216
|
|
|
137
217
|
## MCP Server
|
|
@@ -167,8 +247,8 @@ Engram doesn't just persist data — it gives your agents **continuity**. The ab
|
|
|
167
247
|
|
|
168
248
|
- **v0.1** ✅ SQLite persistence, keyword search
|
|
169
249
|
- **v0.2** ✅ Semantic search via local Ollama embeddings
|
|
170
|
-
- **v0.3**
|
|
171
|
-
- **v0.4**
|
|
250
|
+
- **v0.3** ✅ Graph memory — entity relationships, connected context
|
|
251
|
+
- **v0.4** ✅ Memory consolidation, long-term summarization
|
|
172
252
|
|
|
173
253
|
## The Cartisien Memory Suite
|
|
174
254
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IMemoryAdapter, Memory, SearchOptions, SearchResult } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* In-process MemoryAdapter — no persistence, ideal for testing and ephemeral agents.
|
|
4
|
+
* The simplest possible trace: exists only as long as the process lives.
|
|
5
|
+
*/
|
|
6
|
+
export declare class MemoryAdapter implements IMemoryAdapter {
|
|
7
|
+
private _cache;
|
|
8
|
+
init(): Promise<void>;
|
|
9
|
+
store(memory: Memory): Promise<Memory>;
|
|
10
|
+
get(id: string): Promise<Memory | null>;
|
|
11
|
+
search(embedding: number[], options: Required<SearchOptions>): Promise<SearchResult[]>;
|
|
12
|
+
forget(id: string): Promise<void>;
|
|
13
|
+
list(agentId: string, limit?: number): Promise<Memory[]>;
|
|
14
|
+
close(): Promise<void>;
|
|
15
|
+
get size(): number;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/adapters/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAGtF;;;GAGG;AACH,qBAAa,aAAc,YAAW,cAAc;IAClD,OAAO,CAAC,MAAM,CAA4B;IAEpC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKtC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAcvC,MAAM,CACV,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,GAC/B,OAAO,CAAC,YAAY,EAAE,CAAC;IAepB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAOpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { cosineSimilarity } from '../utils/similarity.js';
|
|
2
|
+
/**
|
|
3
|
+
* In-process MemoryAdapter — no persistence, ideal for testing and ephemeral agents.
|
|
4
|
+
* The simplest possible trace: exists only as long as the process lives.
|
|
5
|
+
*/
|
|
6
|
+
export class MemoryAdapter {
|
|
7
|
+
constructor() {
|
|
8
|
+
this._cache = new Map();
|
|
9
|
+
}
|
|
10
|
+
async init() {
|
|
11
|
+
// nothing to set up
|
|
12
|
+
}
|
|
13
|
+
async store(memory) {
|
|
14
|
+
this._cache.set(memory.id, memory);
|
|
15
|
+
return memory;
|
|
16
|
+
}
|
|
17
|
+
async get(id) {
|
|
18
|
+
const memory = this._cache.get(id) ?? null;
|
|
19
|
+
if (memory) {
|
|
20
|
+
const updated = {
|
|
21
|
+
...memory,
|
|
22
|
+
accessedAt: new Date(),
|
|
23
|
+
accessCount: memory.accessCount + 1,
|
|
24
|
+
};
|
|
25
|
+
this._cache.set(id, updated);
|
|
26
|
+
return updated;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
async search(embedding, options) {
|
|
31
|
+
const results = [];
|
|
32
|
+
for (const memory of this._cache.values()) {
|
|
33
|
+
const score = cosineSimilarity(embedding, memory.embedding);
|
|
34
|
+
if (score >= options.threshold) {
|
|
35
|
+
results.push({ memory, score });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return results
|
|
39
|
+
.sort((a, b) => b.score - a.score)
|
|
40
|
+
.slice(0, options.limit);
|
|
41
|
+
}
|
|
42
|
+
async forget(id) {
|
|
43
|
+
this._cache.delete(id);
|
|
44
|
+
}
|
|
45
|
+
async list(agentId, limit = 50) {
|
|
46
|
+
return [...this._cache.values()]
|
|
47
|
+
.filter((m) => m.agentId === agentId)
|
|
48
|
+
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
|
|
49
|
+
.slice(0, limit);
|
|
50
|
+
}
|
|
51
|
+
async close() {
|
|
52
|
+
this._cache.clear();
|
|
53
|
+
}
|
|
54
|
+
get size() {
|
|
55
|
+
return this._cache.size;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/adapters/memory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAEzD;;;GAGG;AACH,MAAM,OAAO,aAAa;IAA1B;QACU,WAAM,GAAG,IAAI,GAAG,EAAkB,CAAA;IA6D5C,CAAC;IA3DC,KAAK,CAAC,IAAI;QACR,oBAAoB;IACtB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;QAClC,OAAO,MAAM,CAAA;IACf,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAU;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAA;QAC1C,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,OAAO,GAAW;gBACtB,GAAG,MAAM;gBACT,UAAU,EAAE,IAAI,IAAI,EAAE;gBACtB,WAAW,EAAE,MAAM,CAAC,WAAW,GAAG,CAAC;aACpC,CAAA;YACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;YAC5B,OAAO,OAAO,CAAA;QAChB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,KAAK,CAAC,MAAM,CACV,SAAmB,EACnB,OAAgC;QAEhC,MAAM,OAAO,GAAmB,EAAE,CAAA;QAElC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YAC3D,IAAI,KAAK,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBAC/B,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;YACjC,CAAC;QACH,CAAC;QAED,OAAO,OAAO;aACX,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;aACjC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAe,EAAE,KAAK,GAAG,EAAE;QACpC,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;aAC7B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC;aACpC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;aAC7D,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACpB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAA;IACzB,CAAC;CACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { IMemoryAdapter, Memory, SearchOptions, SearchResult } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* PostgresAdapter — uses pgvector for semantic similarity search.
|
|
4
|
+
*
|
|
5
|
+
* TODO: implement with `pg` + pgvector extension.
|
|
6
|
+
* Requires: CREATE EXTENSION IF NOT EXISTS vector;
|
|
7
|
+
*
|
|
8
|
+
* Schema:
|
|
9
|
+
* CREATE TABLE engram_memories (
|
|
10
|
+
* id TEXT PRIMARY KEY,
|
|
11
|
+
* agent_id TEXT NOT NULL,
|
|
12
|
+
* content TEXT NOT NULL,
|
|
13
|
+
* embedding vector(1536),
|
|
14
|
+
* importance FLOAT NOT NULL DEFAULT 0.5,
|
|
15
|
+
* metadata JSONB NOT NULL DEFAULT '{}',
|
|
16
|
+
* created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
17
|
+
* accessed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
18
|
+
* access_count INT NOT NULL DEFAULT 0
|
|
19
|
+
* );
|
|
20
|
+
* CREATE INDEX ON engram_memories USING ivfflat (embedding vector_cosine_ops);
|
|
21
|
+
*/
|
|
22
|
+
export declare class PostgresAdapter implements IMemoryAdapter {
|
|
23
|
+
private readonly connectionString;
|
|
24
|
+
constructor(connectionString: string);
|
|
25
|
+
init(): Promise<void>;
|
|
26
|
+
store(_memory: Memory): Promise<Memory>;
|
|
27
|
+
get(_id: string): Promise<Memory | null>;
|
|
28
|
+
search(_embedding: number[], _options: Required<SearchOptions>): Promise<SearchResult[]>;
|
|
29
|
+
forget(_id: string): Promise<void>;
|
|
30
|
+
list(_agentId: string, _limit?: number): Promise<Memory[]>;
|
|
31
|
+
close(): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=postgres.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/adapters/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAEtF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,eAAgB,YAAW,cAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;gBAAhB,gBAAgB,EAAE,MAAM;IAE/C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIvC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIxC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAIxF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAI1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgresAdapter — uses pgvector for semantic similarity search.
|
|
3
|
+
*
|
|
4
|
+
* TODO: implement with `pg` + pgvector extension.
|
|
5
|
+
* Requires: CREATE EXTENSION IF NOT EXISTS vector;
|
|
6
|
+
*
|
|
7
|
+
* Schema:
|
|
8
|
+
* CREATE TABLE engram_memories (
|
|
9
|
+
* id TEXT PRIMARY KEY,
|
|
10
|
+
* agent_id TEXT NOT NULL,
|
|
11
|
+
* content TEXT NOT NULL,
|
|
12
|
+
* embedding vector(1536),
|
|
13
|
+
* importance FLOAT NOT NULL DEFAULT 0.5,
|
|
14
|
+
* metadata JSONB NOT NULL DEFAULT '{}',
|
|
15
|
+
* created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
16
|
+
* accessed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
17
|
+
* access_count INT NOT NULL DEFAULT 0
|
|
18
|
+
* );
|
|
19
|
+
* CREATE INDEX ON engram_memories USING ivfflat (embedding vector_cosine_ops);
|
|
20
|
+
*/
|
|
21
|
+
export class PostgresAdapter {
|
|
22
|
+
constructor(connectionString) {
|
|
23
|
+
this.connectionString = connectionString;
|
|
24
|
+
}
|
|
25
|
+
async init() {
|
|
26
|
+
throw new Error('PostgresAdapter not yet implemented. Use MemoryAdapter for now.');
|
|
27
|
+
}
|
|
28
|
+
async store(_memory) {
|
|
29
|
+
throw new Error('Not implemented');
|
|
30
|
+
}
|
|
31
|
+
async get(_id) {
|
|
32
|
+
throw new Error('Not implemented');
|
|
33
|
+
}
|
|
34
|
+
async search(_embedding, _options) {
|
|
35
|
+
throw new Error('Not implemented');
|
|
36
|
+
}
|
|
37
|
+
async forget(_id) {
|
|
38
|
+
throw new Error('Not implemented');
|
|
39
|
+
}
|
|
40
|
+
async list(_agentId, _limit) {
|
|
41
|
+
throw new Error('Not implemented');
|
|
42
|
+
}
|
|
43
|
+
async close() {
|
|
44
|
+
// no-op until implemented
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=postgres.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../src/adapters/postgres.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,eAAe;IAC1B,YAA6B,gBAAwB;QAAxB,qBAAgB,GAAhB,gBAAgB,CAAQ;IAAG,CAAC;IAEzD,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;IACpF,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAe;QACzB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,UAAoB,EAAE,QAAiC;QAClE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAgB,EAAE,MAAe;QAC1C,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,KAAK;QACT,0BAA0B;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IMemoryAdapter, Memory, SearchOptions, SearchResult } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* SqliteAdapter — local file-backed persistence with vector search.
|
|
4
|
+
*
|
|
5
|
+
* TODO: implement with `better-sqlite3` + manual cosine similarity
|
|
6
|
+
* (sqlite-vss or sqlite-vec extension optional).
|
|
7
|
+
*/
|
|
8
|
+
export declare class SqliteAdapter implements IMemoryAdapter {
|
|
9
|
+
private readonly filePath;
|
|
10
|
+
constructor(filePath: string);
|
|
11
|
+
init(): Promise<void>;
|
|
12
|
+
store(_memory: Memory): Promise<Memory>;
|
|
13
|
+
get(_id: string): Promise<Memory | null>;
|
|
14
|
+
search(_embedding: number[], _options: Required<SearchOptions>): Promise<SearchResult[]>;
|
|
15
|
+
forget(_id: string): Promise<void>;
|
|
16
|
+
list(_agentId: string, _limit?: number): Promise<Memory[]>;
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=sqlite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/adapters/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAEtF;;;;;GAKG;AACH,qBAAa,aAAc,YAAW,cAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAEvC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIvC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIxC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAIxF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAI1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SqliteAdapter — local file-backed persistence with vector search.
|
|
3
|
+
*
|
|
4
|
+
* TODO: implement with `better-sqlite3` + manual cosine similarity
|
|
5
|
+
* (sqlite-vss or sqlite-vec extension optional).
|
|
6
|
+
*/
|
|
7
|
+
export class SqliteAdapter {
|
|
8
|
+
constructor(filePath) {
|
|
9
|
+
this.filePath = filePath;
|
|
10
|
+
}
|
|
11
|
+
async init() {
|
|
12
|
+
throw new Error('SqliteAdapter not yet implemented. Use MemoryAdapter for now.');
|
|
13
|
+
}
|
|
14
|
+
async store(_memory) {
|
|
15
|
+
throw new Error('Not implemented');
|
|
16
|
+
}
|
|
17
|
+
async get(_id) {
|
|
18
|
+
throw new Error('Not implemented');
|
|
19
|
+
}
|
|
20
|
+
async search(_embedding, _options) {
|
|
21
|
+
throw new Error('Not implemented');
|
|
22
|
+
}
|
|
23
|
+
async forget(_id) {
|
|
24
|
+
throw new Error('Not implemented');
|
|
25
|
+
}
|
|
26
|
+
async list(_agentId, _limit) {
|
|
27
|
+
throw new Error('Not implemented');
|
|
28
|
+
}
|
|
29
|
+
async close() {
|
|
30
|
+
// no-op until implemented
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=sqlite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/adapters/sqlite.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,OAAO,aAAa;IACxB,YAA6B,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;IAAG,CAAC;IAEjD,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAA;IAClF,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAe;QACzB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,UAAoB,EAAE,QAAiC;QAClE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAgB,EAAE,MAAe;QAC1C,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,KAAK;QACT,0BAA0B;IAC5B,CAAC;CACF"}
|
package/dist/engram.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { EngramConfig, Memory, MemoryInput, SearchOptions, SearchResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Engram — persistent semantic memory for AI agents.
|
|
4
|
+
*
|
|
5
|
+
* "We no longer live in the age of cogito. We live in the age of the trace."
|
|
6
|
+
* — Derrida (via Orlo Rodriguez, "I Compute, Therefore Am I?")
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* const mem = new Engram({ adapter: 'memory', agentId: 'my-agent' })
|
|
10
|
+
* await mem.wake()
|
|
11
|
+
* await mem.store({ content: 'The user prefers dark mode' })
|
|
12
|
+
* const results = await mem.search('user preferences')
|
|
13
|
+
* await mem.sleep()
|
|
14
|
+
*/
|
|
15
|
+
export declare class Engram {
|
|
16
|
+
private adapter;
|
|
17
|
+
private readonly config;
|
|
18
|
+
private initialized;
|
|
19
|
+
private sessionStart;
|
|
20
|
+
constructor(config: EngramConfig);
|
|
21
|
+
/**
|
|
22
|
+
* Initialize the adapter and record session start.
|
|
23
|
+
* Call this at agent startup.
|
|
24
|
+
*/
|
|
25
|
+
wake(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Persist state and close connections.
|
|
28
|
+
* Call this at agent shutdown.
|
|
29
|
+
*/
|
|
30
|
+
sleep(): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Store a memory. Embeds content automatically.
|
|
33
|
+
*/
|
|
34
|
+
store(input: MemoryInput): Promise<Memory>;
|
|
35
|
+
/**
|
|
36
|
+
* Store multiple memories in parallel.
|
|
37
|
+
*/
|
|
38
|
+
storeMany(inputs: MemoryInput[]): Promise<Memory[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Semantic search over stored memories.
|
|
41
|
+
*/
|
|
42
|
+
search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Retrieve a memory by ID.
|
|
45
|
+
*/
|
|
46
|
+
get(id: string): Promise<Memory | null>;
|
|
47
|
+
/**
|
|
48
|
+
* Delete a memory permanently.
|
|
49
|
+
*/
|
|
50
|
+
forget(id: string): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* List recent memories for this agent.
|
|
53
|
+
*/
|
|
54
|
+
list(limit?: number): Promise<Memory[]>;
|
|
55
|
+
private ensureReady;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=engram.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engram.d.ts","sourceRoot":"","sources":["../src/engram.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EAEZ,MAAM,EACN,WAAW,EACX,aAAa,EACb,YAAY,EACb,MAAM,YAAY,CAAA;AAMnB;;;;;;;;;;;;GAYG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,YAAY,CAAoB;gBAE5B,MAAM,EAAE,YAAY;IAiChC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B;;OAEG;IACG,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAqBhD;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIzD;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAWjF;;OAEG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAK7C;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC;;OAEG;IACG,IAAI,CAAC,KAAK,SAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAS3B,WAAW;CAK1B"}
|
package/dist/engram.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { MemoryAdapter } from './adapters/memory.js';
|
|
3
|
+
import { PostgresAdapter } from './adapters/postgres.js';
|
|
4
|
+
import { SqliteAdapter } from './adapters/sqlite.js';
|
|
5
|
+
import { embedText, DEFAULT_DIMENSIONS } from './utils/embeddings.js';
|
|
6
|
+
/**
|
|
7
|
+
* Engram — persistent semantic memory for AI agents.
|
|
8
|
+
*
|
|
9
|
+
* "We no longer live in the age of cogito. We live in the age of the trace."
|
|
10
|
+
* — Derrida (via Orlo Rodriguez, "I Compute, Therefore Am I?")
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* const mem = new Engram({ adapter: 'memory', agentId: 'my-agent' })
|
|
14
|
+
* await mem.wake()
|
|
15
|
+
* await mem.store({ content: 'The user prefers dark mode' })
|
|
16
|
+
* const results = await mem.search('user preferences')
|
|
17
|
+
* await mem.sleep()
|
|
18
|
+
*/
|
|
19
|
+
export class Engram {
|
|
20
|
+
constructor(config) {
|
|
21
|
+
this.initialized = false;
|
|
22
|
+
this.sessionStart = null;
|
|
23
|
+
this.config = {
|
|
24
|
+
adapter: config.adapter,
|
|
25
|
+
agentId: config.agentId,
|
|
26
|
+
connectionString: config.connectionString ?? '',
|
|
27
|
+
embeddingDimensions: config.embeddingDimensions ?? DEFAULT_DIMENSIONS,
|
|
28
|
+
};
|
|
29
|
+
switch (config.adapter) {
|
|
30
|
+
case 'memory':
|
|
31
|
+
this.adapter = new MemoryAdapter();
|
|
32
|
+
break;
|
|
33
|
+
case 'postgres':
|
|
34
|
+
if (!config.connectionString) {
|
|
35
|
+
throw new Error('connectionString required for postgres adapter');
|
|
36
|
+
}
|
|
37
|
+
this.adapter = new PostgresAdapter(config.connectionString);
|
|
38
|
+
break;
|
|
39
|
+
case 'sqlite':
|
|
40
|
+
if (!config.connectionString) {
|
|
41
|
+
throw new Error('connectionString (file path) required for sqlite adapter');
|
|
42
|
+
}
|
|
43
|
+
this.adapter = new SqliteAdapter(config.connectionString);
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
throw new Error(`Unknown adapter: ${config.adapter}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Lifecycle
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
/**
|
|
53
|
+
* Initialize the adapter and record session start.
|
|
54
|
+
* Call this at agent startup.
|
|
55
|
+
*/
|
|
56
|
+
async wake() {
|
|
57
|
+
if (!this.initialized) {
|
|
58
|
+
await this.adapter.init();
|
|
59
|
+
this.initialized = true;
|
|
60
|
+
}
|
|
61
|
+
this.sessionStart = new Date();
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Persist state and close connections.
|
|
65
|
+
* Call this at agent shutdown.
|
|
66
|
+
*/
|
|
67
|
+
async sleep() {
|
|
68
|
+
if (this.sessionStart) {
|
|
69
|
+
const duration = Date.now() - this.sessionStart.getTime();
|
|
70
|
+
// TODO: emit session summary to a "session" memory
|
|
71
|
+
void duration;
|
|
72
|
+
this.sessionStart = null;
|
|
73
|
+
}
|
|
74
|
+
await this.adapter.close();
|
|
75
|
+
this.initialized = false;
|
|
76
|
+
}
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// Core API
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
/**
|
|
81
|
+
* Store a memory. Embeds content automatically.
|
|
82
|
+
*/
|
|
83
|
+
async store(input) {
|
|
84
|
+
await this.ensureReady();
|
|
85
|
+
const embedding = await embedText(input.content, this.config.embeddingDimensions);
|
|
86
|
+
const now = new Date();
|
|
87
|
+
const memory = {
|
|
88
|
+
id: randomUUID(),
|
|
89
|
+
agentId: this.config.agentId,
|
|
90
|
+
content: input.content,
|
|
91
|
+
embedding,
|
|
92
|
+
importance: input.importance ?? 0.5,
|
|
93
|
+
metadata: input.metadata ?? {},
|
|
94
|
+
createdAt: now,
|
|
95
|
+
accessedAt: now,
|
|
96
|
+
accessCount: 0,
|
|
97
|
+
};
|
|
98
|
+
return this.adapter.store(memory);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Store multiple memories in parallel.
|
|
102
|
+
*/
|
|
103
|
+
async storeMany(inputs) {
|
|
104
|
+
return Promise.all(inputs.map((input) => this.store(input)));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Semantic search over stored memories.
|
|
108
|
+
*/
|
|
109
|
+
async search(query, options = {}) {
|
|
110
|
+
await this.ensureReady();
|
|
111
|
+
const embedding = await embedText(query, this.config.embeddingDimensions);
|
|
112
|
+
return this.adapter.search(embedding, {
|
|
113
|
+
limit: options.limit ?? 10,
|
|
114
|
+
threshold: options.threshold ?? 0.0,
|
|
115
|
+
filter: options.filter ?? {},
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Retrieve a memory by ID.
|
|
120
|
+
*/
|
|
121
|
+
async get(id) {
|
|
122
|
+
await this.ensureReady();
|
|
123
|
+
return this.adapter.get(id);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Delete a memory permanently.
|
|
127
|
+
*/
|
|
128
|
+
async forget(id) {
|
|
129
|
+
await this.ensureReady();
|
|
130
|
+
return this.adapter.forget(id);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* List recent memories for this agent.
|
|
134
|
+
*/
|
|
135
|
+
async list(limit = 50) {
|
|
136
|
+
await this.ensureReady();
|
|
137
|
+
return this.adapter.list(this.config.agentId, limit);
|
|
138
|
+
}
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
// Internals
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
async ensureReady() {
|
|
143
|
+
if (!this.initialized) {
|
|
144
|
+
await this.wake();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=engram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engram.js","sourceRoot":"","sources":["../src/engram.ts"],"names":[],"mappings":"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"}
|