@cartisien/engram 0.3.0 → 0.4.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 +36 -2
- 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 +64 -37
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +243 -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 +1 -1
- 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
|
|
|
@@ -127,11 +129,43 @@ await memory.forget('session_abc', { id: 'entry_id' }); // one
|
|
|
127
129
|
await memory.forget('session_abc', { before: new Date() }); // old entries
|
|
128
130
|
```
|
|
129
131
|
|
|
132
|
+
### `graph(sessionId, entity)`
|
|
133
|
+
|
|
134
|
+
Returns a one-hop relationship map for a named entity — all connected entities and the memories that link them.
|
|
135
|
+
|
|
136
|
+
Requires `graphMemory: true` in config and a running Ollama instance with `qwen2.5:32b` (or override via `graphModel`).
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const memory = new Engram({
|
|
140
|
+
dbPath: './memory.db',
|
|
141
|
+
graphMemory: true,
|
|
142
|
+
graphModel: 'qwen2.5:32b', // default
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const graph = await memory.graph('session_abc', 'GovScout');
|
|
146
|
+
// {
|
|
147
|
+
// entity: 'GovScout',
|
|
148
|
+
// edges: [
|
|
149
|
+
// { relation: 'uses', target: 'MUI', sourceMemoryId: '...' },
|
|
150
|
+
// { relation: 'built_by', target: 'Jeff', sourceMemoryId: '...' },
|
|
151
|
+
// ],
|
|
152
|
+
// memories: [ { content: '...', ... } ]
|
|
153
|
+
// }
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### `recall()` with graph augmentation
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
const results = await memory.recall('session_abc', 'what is GovScout?', 5, {
|
|
160
|
+
includeGraph: true, // augment top results with graph-connected memories
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
130
164
|
### `stats(sessionId)`
|
|
131
165
|
|
|
132
166
|
```typescript
|
|
133
167
|
const stats = await memory.stats('session_abc');
|
|
134
|
-
// { total: 42, byRole: { user: 21, assistant: 21 }, withEmbeddings: 42,
|
|
168
|
+
// { total: 42, byRole: { user: 21, assistant: 21 }, withEmbeddings: 42, graphNodes: 18, graphEdges: 31 }
|
|
135
169
|
```
|
|
136
170
|
|
|
137
171
|
## MCP Server
|
|
@@ -167,7 +201,7 @@ Engram doesn't just persist data — it gives your agents **continuity**. The ab
|
|
|
167
201
|
|
|
168
202
|
- **v0.1** ✅ SQLite persistence, keyword search
|
|
169
203
|
- **v0.2** ✅ Semantic search via local Ollama embeddings
|
|
170
|
-
- **v0.3**
|
|
204
|
+
- **v0.3** ✅ Graph memory — entity relationships, connected context
|
|
171
205
|
- **v0.4** 📋 Memory consolidation, long-term summarization
|
|
172
206
|
|
|
173
207
|
## The Cartisien Memory Suite
|
|
@@ -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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"}
|