agentdb 1.3.12 → 1.3.13
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/dist/agentdb.min.js +4 -4
- package/dist/cli/agentdb-cli.d.ts.map +1 -1
- package/dist/cli/agentdb-cli.js +74 -6
- package/dist/cli/agentdb-cli.js.map +1 -1
- package/dist/db-fallback.d.ts +4 -0
- package/dist/db-fallback.d.ts.map +1 -1
- package/dist/db-fallback.js +11 -1
- package/dist/db-fallback.js.map +1 -1
- package/dist/mcp/agentdb-mcp-server.js +2 -2
- package/dist/mcp/agentdb-mcp-server.js.map +1 -1
- package/dist/schemas/frontier-schema.sql +341 -0
- package/dist/schemas/schema.sql +382 -0
- package/package.json +5 -4
- package/src/cli/agentdb-cli.ts +79 -6
- package/src/db-fallback.ts +21 -8
- package/src/mcp/agentdb-mcp-server.ts +2 -1
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- AgentDB State-of-the-Art Memory Schema
|
|
3
|
+
-- ============================================================================
|
|
4
|
+
-- Implements 5 cutting-edge memory patterns for autonomous agents:
|
|
5
|
+
-- 1. Reflexion-style episodic replay
|
|
6
|
+
-- 2. Skill library from trajectories
|
|
7
|
+
-- 3. Structured mixed memory (facts + summaries)
|
|
8
|
+
-- 4. Episodic segmentation and consolidation
|
|
9
|
+
-- 5. Graph-aware recall
|
|
10
|
+
-- ============================================================================
|
|
11
|
+
|
|
12
|
+
-- Enable foreign keys
|
|
13
|
+
PRAGMA foreign_keys = ON;
|
|
14
|
+
|
|
15
|
+
-- ============================================================================
|
|
16
|
+
-- Pattern 1: Reflexion-Style Episodic Replay
|
|
17
|
+
-- ============================================================================
|
|
18
|
+
-- Store self-critique and outcomes after each attempt.
|
|
19
|
+
-- Retrieve nearest failures and fixes before the next run.
|
|
20
|
+
|
|
21
|
+
CREATE TABLE IF NOT EXISTS episodes (
|
|
22
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23
|
+
ts INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
24
|
+
session_id TEXT NOT NULL,
|
|
25
|
+
task TEXT NOT NULL,
|
|
26
|
+
input TEXT,
|
|
27
|
+
output TEXT,
|
|
28
|
+
critique TEXT,
|
|
29
|
+
reward REAL DEFAULT 0.0,
|
|
30
|
+
success BOOLEAN DEFAULT 0,
|
|
31
|
+
latency_ms INTEGER,
|
|
32
|
+
tokens_used INTEGER,
|
|
33
|
+
tags TEXT, -- JSON array of tags
|
|
34
|
+
metadata JSON,
|
|
35
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_episodes_ts ON episodes(ts DESC);
|
|
39
|
+
CREATE INDEX IF NOT EXISTS idx_episodes_session ON episodes(session_id);
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_episodes_reward ON episodes(reward DESC);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_episodes_task ON episodes(task);
|
|
42
|
+
|
|
43
|
+
-- Vector embeddings for episodes (384-dim for all-MiniLM-L6-v2)
|
|
44
|
+
-- Will use sqlite-vec when available, fallback to JSON storage
|
|
45
|
+
CREATE TABLE IF NOT EXISTS episode_embeddings (
|
|
46
|
+
episode_id INTEGER PRIMARY KEY,
|
|
47
|
+
embedding BLOB NOT NULL, -- Float32Array as BLOB
|
|
48
|
+
embedding_model TEXT DEFAULT 'all-MiniLM-L6-v2',
|
|
49
|
+
FOREIGN KEY(episode_id) REFERENCES episodes(id) ON DELETE CASCADE
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
-- ============================================================================
|
|
53
|
+
-- Pattern 2: Skill Library from Trajectories
|
|
54
|
+
-- ============================================================================
|
|
55
|
+
-- Promote high-reward traces into reusable "skills" with typed IO.
|
|
56
|
+
|
|
57
|
+
CREATE TABLE IF NOT EXISTS skills (
|
|
58
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
59
|
+
name TEXT UNIQUE NOT NULL,
|
|
60
|
+
description TEXT,
|
|
61
|
+
signature JSON NOT NULL, -- {inputs: {...}, outputs: {...}}
|
|
62
|
+
code TEXT, -- Tool call manifest or code template
|
|
63
|
+
success_rate REAL DEFAULT 0.0,
|
|
64
|
+
uses INTEGER DEFAULT 0,
|
|
65
|
+
avg_reward REAL DEFAULT 0.0,
|
|
66
|
+
avg_latency_ms INTEGER DEFAULT 0,
|
|
67
|
+
created_from_episode INTEGER, -- Source episode ID
|
|
68
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
69
|
+
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
70
|
+
last_used_at INTEGER,
|
|
71
|
+
metadata JSON,
|
|
72
|
+
FOREIGN KEY(created_from_episode) REFERENCES episodes(id)
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_skills_success ON skills(success_rate DESC);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_skills_uses ON skills(uses DESC);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_skills_name ON skills(name);
|
|
78
|
+
|
|
79
|
+
-- Skill relationships and composition
|
|
80
|
+
CREATE TABLE IF NOT EXISTS skill_links (
|
|
81
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
82
|
+
parent_skill_id INTEGER NOT NULL,
|
|
83
|
+
child_skill_id INTEGER NOT NULL,
|
|
84
|
+
relationship TEXT NOT NULL, -- 'prerequisite', 'alternative', 'refinement', 'composition'
|
|
85
|
+
weight REAL DEFAULT 1.0,
|
|
86
|
+
metadata JSON,
|
|
87
|
+
FOREIGN KEY(parent_skill_id) REFERENCES skills(id) ON DELETE CASCADE,
|
|
88
|
+
FOREIGN KEY(child_skill_id) REFERENCES skills(id) ON DELETE CASCADE,
|
|
89
|
+
UNIQUE(parent_skill_id, child_skill_id, relationship)
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
CREATE INDEX IF NOT EXISTS idx_skill_links_parent ON skill_links(parent_skill_id);
|
|
93
|
+
CREATE INDEX IF NOT EXISTS idx_skill_links_child ON skill_links(child_skill_id);
|
|
94
|
+
|
|
95
|
+
-- Skill embeddings for semantic search
|
|
96
|
+
CREATE TABLE IF NOT EXISTS skill_embeddings (
|
|
97
|
+
skill_id INTEGER PRIMARY KEY,
|
|
98
|
+
embedding BLOB NOT NULL,
|
|
99
|
+
embedding_model TEXT DEFAULT 'all-MiniLM-L6-v2',
|
|
100
|
+
FOREIGN KEY(skill_id) REFERENCES skills(id) ON DELETE CASCADE
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
-- ============================================================================
|
|
104
|
+
-- Pattern 3: Structured Mixed Memory (Facts + Summaries)
|
|
105
|
+
-- ============================================================================
|
|
106
|
+
-- Combine facts, summaries, and vectors to avoid over-embedding.
|
|
107
|
+
|
|
108
|
+
-- Atomic facts as triples (subject-predicate-object)
|
|
109
|
+
CREATE TABLE IF NOT EXISTS facts (
|
|
110
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
111
|
+
subject TEXT NOT NULL,
|
|
112
|
+
predicate TEXT NOT NULL,
|
|
113
|
+
object TEXT NOT NULL,
|
|
114
|
+
source_type TEXT, -- 'episode', 'skill', 'external', 'inferred'
|
|
115
|
+
source_id INTEGER,
|
|
116
|
+
confidence REAL DEFAULT 1.0,
|
|
117
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
118
|
+
expires_at INTEGER, -- TTL for temporal facts
|
|
119
|
+
metadata JSON
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
CREATE INDEX IF NOT EXISTS idx_facts_subject ON facts(subject);
|
|
123
|
+
CREATE INDEX IF NOT EXISTS idx_facts_predicate ON facts(predicate);
|
|
124
|
+
CREATE INDEX IF NOT EXISTS idx_facts_object ON facts(object);
|
|
125
|
+
CREATE INDEX IF NOT EXISTS idx_facts_source ON facts(source_type, source_id);
|
|
126
|
+
CREATE INDEX IF NOT EXISTS idx_facts_expires ON facts(expires_at) WHERE expires_at IS NOT NULL;
|
|
127
|
+
|
|
128
|
+
-- Notes and summaries with semantic embeddings
|
|
129
|
+
CREATE TABLE IF NOT EXISTS notes (
|
|
130
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
131
|
+
title TEXT,
|
|
132
|
+
text TEXT NOT NULL,
|
|
133
|
+
summary TEXT, -- Condensed version for context
|
|
134
|
+
note_type TEXT DEFAULT 'general', -- 'insight', 'constraint', 'goal', 'observation'
|
|
135
|
+
importance REAL DEFAULT 0.5,
|
|
136
|
+
access_count INTEGER DEFAULT 0,
|
|
137
|
+
last_accessed_at INTEGER,
|
|
138
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
139
|
+
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
140
|
+
metadata JSON
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
CREATE INDEX IF NOT EXISTS idx_notes_type ON notes(note_type);
|
|
144
|
+
CREATE INDEX IF NOT EXISTS idx_notes_importance ON notes(importance DESC);
|
|
145
|
+
CREATE INDEX IF NOT EXISTS idx_notes_accessed ON notes(last_accessed_at DESC);
|
|
146
|
+
|
|
147
|
+
-- Note embeddings (only for summaries to reduce storage)
|
|
148
|
+
CREATE TABLE IF NOT EXISTS note_embeddings (
|
|
149
|
+
note_id INTEGER PRIMARY KEY,
|
|
150
|
+
embedding BLOB NOT NULL,
|
|
151
|
+
embedding_model TEXT DEFAULT 'all-MiniLM-L6-v2',
|
|
152
|
+
FOREIGN KEY(note_id) REFERENCES notes(id) ON DELETE CASCADE
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
-- ============================================================================
|
|
156
|
+
-- Pattern 4: Episodic Segmentation and Consolidation
|
|
157
|
+
-- ============================================================================
|
|
158
|
+
-- Segment long tasks into events and consolidate into compact memories.
|
|
159
|
+
|
|
160
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
161
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
162
|
+
session_id TEXT NOT NULL,
|
|
163
|
+
episode_id INTEGER, -- Link to parent episode
|
|
164
|
+
step INTEGER NOT NULL,
|
|
165
|
+
phase TEXT, -- 'planning', 'execution', 'reflection', 'learning'
|
|
166
|
+
role TEXT, -- 'user', 'assistant', 'system', 'tool'
|
|
167
|
+
content TEXT NOT NULL,
|
|
168
|
+
features JSON, -- Extracted features for learning
|
|
169
|
+
tool_calls JSON, -- Tool invocations in this event
|
|
170
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
171
|
+
FOREIGN KEY(episode_id) REFERENCES episodes(id) ON DELETE CASCADE
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
CREATE INDEX IF NOT EXISTS idx_events_session ON events(session_id, step);
|
|
175
|
+
CREATE INDEX IF NOT EXISTS idx_events_phase ON events(phase);
|
|
176
|
+
CREATE INDEX IF NOT EXISTS idx_events_episode ON events(episode_id);
|
|
177
|
+
|
|
178
|
+
-- Consolidated memories from event windows
|
|
179
|
+
CREATE TABLE IF NOT EXISTS consolidated_memories (
|
|
180
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
181
|
+
session_id TEXT NOT NULL,
|
|
182
|
+
start_event_id INTEGER NOT NULL,
|
|
183
|
+
end_event_id INTEGER NOT NULL,
|
|
184
|
+
phase TEXT,
|
|
185
|
+
summary TEXT NOT NULL,
|
|
186
|
+
key_insights JSON, -- Extracted learnings
|
|
187
|
+
success_patterns JSON, -- What worked
|
|
188
|
+
failure_patterns JSON, -- What didn't work
|
|
189
|
+
quality_score REAL DEFAULT 0.5,
|
|
190
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
191
|
+
FOREIGN KEY(start_event_id) REFERENCES events(id),
|
|
192
|
+
FOREIGN KEY(end_event_id) REFERENCES events(id)
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
CREATE INDEX IF NOT EXISTS idx_consolidated_session ON consolidated_memories(session_id);
|
|
196
|
+
CREATE INDEX IF NOT EXISTS idx_consolidated_quality ON consolidated_memories(quality_score DESC);
|
|
197
|
+
|
|
198
|
+
-- ============================================================================
|
|
199
|
+
-- Pattern 5: Graph-Aware Recall (Lightweight GraphRAG)
|
|
200
|
+
-- ============================================================================
|
|
201
|
+
-- Build a lightweight GraphRAG overlay for experiences.
|
|
202
|
+
|
|
203
|
+
CREATE TABLE IF NOT EXISTS exp_nodes (
|
|
204
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
205
|
+
kind TEXT NOT NULL, -- 'task', 'skill', 'concept', 'tool', 'outcome'
|
|
206
|
+
label TEXT NOT NULL,
|
|
207
|
+
payload JSON,
|
|
208
|
+
centrality REAL DEFAULT 0.0, -- Graph importance metric
|
|
209
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
210
|
+
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
CREATE INDEX IF NOT EXISTS idx_exp_nodes_kind ON exp_nodes(kind);
|
|
214
|
+
CREATE INDEX IF NOT EXISTS idx_exp_nodes_label ON exp_nodes(label);
|
|
215
|
+
CREATE INDEX IF NOT EXISTS idx_exp_nodes_centrality ON exp_nodes(centrality DESC);
|
|
216
|
+
|
|
217
|
+
CREATE TABLE IF NOT EXISTS exp_edges (
|
|
218
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
219
|
+
src_node_id INTEGER NOT NULL,
|
|
220
|
+
dst_node_id INTEGER NOT NULL,
|
|
221
|
+
relationship TEXT NOT NULL, -- 'requires', 'produces', 'similar_to', 'refines', 'part_of'
|
|
222
|
+
weight REAL DEFAULT 1.0,
|
|
223
|
+
metadata JSON,
|
|
224
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
225
|
+
FOREIGN KEY(src_node_id) REFERENCES exp_nodes(id) ON DELETE CASCADE,
|
|
226
|
+
FOREIGN KEY(dst_node_id) REFERENCES exp_nodes(id) ON DELETE CASCADE,
|
|
227
|
+
UNIQUE(src_node_id, dst_node_id, relationship)
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
CREATE INDEX IF NOT EXISTS idx_exp_edges_src ON exp_edges(src_node_id);
|
|
231
|
+
CREATE INDEX IF NOT EXISTS idx_exp_edges_dst ON exp_edges(dst_node_id);
|
|
232
|
+
CREATE INDEX IF NOT EXISTS idx_exp_edges_rel ON exp_edges(relationship);
|
|
233
|
+
|
|
234
|
+
-- Node embeddings for graph-augmented retrieval
|
|
235
|
+
CREATE TABLE IF NOT EXISTS exp_node_embeddings (
|
|
236
|
+
node_id INTEGER PRIMARY KEY,
|
|
237
|
+
embedding BLOB NOT NULL,
|
|
238
|
+
embedding_model TEXT DEFAULT 'all-MiniLM-L6-v2',
|
|
239
|
+
FOREIGN KEY(node_id) REFERENCES exp_nodes(id) ON DELETE CASCADE
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
-- ============================================================================
|
|
243
|
+
-- Memory Management and Scoring
|
|
244
|
+
-- ============================================================================
|
|
245
|
+
|
|
246
|
+
-- Track memory quality scores and usage statistics
|
|
247
|
+
CREATE TABLE IF NOT EXISTS memory_scores (
|
|
248
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
249
|
+
memory_type TEXT NOT NULL, -- 'episode', 'skill', 'note', 'consolidated'
|
|
250
|
+
memory_id INTEGER NOT NULL,
|
|
251
|
+
quality_score REAL NOT NULL,
|
|
252
|
+
novelty_score REAL,
|
|
253
|
+
relevance_score REAL,
|
|
254
|
+
utility_score REAL,
|
|
255
|
+
computed_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
256
|
+
metadata JSON
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
CREATE INDEX IF NOT EXISTS idx_memory_scores_type ON memory_scores(memory_type, memory_id);
|
|
260
|
+
CREATE INDEX IF NOT EXISTS idx_memory_scores_quality ON memory_scores(quality_score DESC);
|
|
261
|
+
|
|
262
|
+
-- Memory access patterns for adaptive retrieval
|
|
263
|
+
CREATE TABLE IF NOT EXISTS memory_access_log (
|
|
264
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
265
|
+
memory_type TEXT NOT NULL,
|
|
266
|
+
memory_id INTEGER NOT NULL,
|
|
267
|
+
query TEXT,
|
|
268
|
+
relevance_score REAL,
|
|
269
|
+
was_useful BOOLEAN,
|
|
270
|
+
feedback JSON,
|
|
271
|
+
accessed_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
CREATE INDEX IF NOT EXISTS idx_access_log_type ON memory_access_log(memory_type, memory_id);
|
|
275
|
+
CREATE INDEX IF NOT EXISTS idx_access_log_time ON memory_access_log(accessed_at DESC);
|
|
276
|
+
|
|
277
|
+
-- ============================================================================
|
|
278
|
+
-- Consolidation and Maintenance
|
|
279
|
+
-- ============================================================================
|
|
280
|
+
|
|
281
|
+
-- Track consolidation jobs and their results
|
|
282
|
+
CREATE TABLE IF NOT EXISTS consolidation_runs (
|
|
283
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
284
|
+
job_type TEXT NOT NULL, -- 'episode_to_skill', 'event_to_memory', 'deduplication', 'pruning'
|
|
285
|
+
records_processed INTEGER DEFAULT 0,
|
|
286
|
+
records_created INTEGER DEFAULT 0,
|
|
287
|
+
records_deleted INTEGER DEFAULT 0,
|
|
288
|
+
duration_ms INTEGER,
|
|
289
|
+
status TEXT DEFAULT 'pending', -- 'pending', 'running', 'completed', 'failed'
|
|
290
|
+
error TEXT,
|
|
291
|
+
started_at INTEGER,
|
|
292
|
+
completed_at INTEGER,
|
|
293
|
+
metadata JSON
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
CREATE INDEX IF NOT EXISTS idx_consolidation_status ON consolidation_runs(status);
|
|
297
|
+
CREATE INDEX IF NOT EXISTS idx_consolidation_type ON consolidation_runs(job_type);
|
|
298
|
+
|
|
299
|
+
-- ============================================================================
|
|
300
|
+
-- Views for Common Queries
|
|
301
|
+
-- ============================================================================
|
|
302
|
+
|
|
303
|
+
-- High-value episodes for skill creation
|
|
304
|
+
CREATE VIEW IF NOT EXISTS skill_candidates AS
|
|
305
|
+
SELECT
|
|
306
|
+
task,
|
|
307
|
+
COUNT(*) as attempt_count,
|
|
308
|
+
AVG(reward) as avg_reward,
|
|
309
|
+
AVG(success) as success_rate,
|
|
310
|
+
MAX(id) as latest_episode_id,
|
|
311
|
+
GROUP_CONCAT(id) as episode_ids
|
|
312
|
+
FROM episodes
|
|
313
|
+
WHERE ts > strftime('%s', 'now') - 86400 * 7 -- Last 7 days
|
|
314
|
+
GROUP BY task
|
|
315
|
+
HAVING attempt_count >= 3 AND avg_reward >= 0.7;
|
|
316
|
+
|
|
317
|
+
-- Top performing skills
|
|
318
|
+
CREATE VIEW IF NOT EXISTS top_skills AS
|
|
319
|
+
SELECT
|
|
320
|
+
s.*,
|
|
321
|
+
COALESCE(s.success_rate, 0) * 0.4 +
|
|
322
|
+
COALESCE(s.uses, 0) * 0.0001 +
|
|
323
|
+
COALESCE(s.avg_reward, 0) * 0.6 as composite_score
|
|
324
|
+
FROM skills s
|
|
325
|
+
ORDER BY composite_score DESC;
|
|
326
|
+
|
|
327
|
+
-- Recent high-quality memories
|
|
328
|
+
CREATE VIEW IF NOT EXISTS recent_quality_memories AS
|
|
329
|
+
SELECT
|
|
330
|
+
'episode' as type, id, task as title, critique as content, reward as score, created_at
|
|
331
|
+
FROM episodes
|
|
332
|
+
WHERE reward >= 0.7 AND ts > strftime('%s', 'now') - 86400 * 3
|
|
333
|
+
UNION ALL
|
|
334
|
+
SELECT
|
|
335
|
+
'note' as type, id, title, summary as content, importance as score, created_at
|
|
336
|
+
FROM notes
|
|
337
|
+
WHERE importance >= 0.7 AND created_at > strftime('%s', 'now') - 86400 * 3
|
|
338
|
+
UNION ALL
|
|
339
|
+
SELECT
|
|
340
|
+
'consolidated' as type, id, session_id as title, summary as content, quality_score as score, created_at
|
|
341
|
+
FROM consolidated_memories
|
|
342
|
+
WHERE quality_score >= 0.7 AND created_at > strftime('%s', 'now') - 86400 * 3
|
|
343
|
+
ORDER BY created_at DESC;
|
|
344
|
+
|
|
345
|
+
-- ============================================================================
|
|
346
|
+
-- Triggers for Auto-Maintenance
|
|
347
|
+
-- ============================================================================
|
|
348
|
+
|
|
349
|
+
-- Update skill usage statistics
|
|
350
|
+
CREATE TRIGGER IF NOT EXISTS update_skill_last_used
|
|
351
|
+
AFTER UPDATE OF uses ON skills
|
|
352
|
+
BEGIN
|
|
353
|
+
UPDATE skills SET last_used_at = strftime('%s', 'now') WHERE id = NEW.id;
|
|
354
|
+
END;
|
|
355
|
+
|
|
356
|
+
-- Update note access tracking
|
|
357
|
+
CREATE TRIGGER IF NOT EXISTS update_note_access
|
|
358
|
+
AFTER UPDATE OF access_count ON notes
|
|
359
|
+
BEGIN
|
|
360
|
+
UPDATE notes SET last_accessed_at = strftime('%s', 'now') WHERE id = NEW.id;
|
|
361
|
+
END;
|
|
362
|
+
|
|
363
|
+
-- Auto-update timestamps
|
|
364
|
+
CREATE TRIGGER IF NOT EXISTS update_skill_timestamp
|
|
365
|
+
AFTER UPDATE ON skills
|
|
366
|
+
BEGIN
|
|
367
|
+
UPDATE skills SET updated_at = strftime('%s', 'now') WHERE id = NEW.id;
|
|
368
|
+
END;
|
|
369
|
+
|
|
370
|
+
CREATE TRIGGER IF NOT EXISTS update_note_timestamp
|
|
371
|
+
AFTER UPDATE ON notes
|
|
372
|
+
BEGIN
|
|
373
|
+
UPDATE notes SET updated_at = strftime('%s', 'now') WHERE id = NEW.id;
|
|
374
|
+
END;
|
|
375
|
+
|
|
376
|
+
-- ============================================================================
|
|
377
|
+
-- Initialization Complete
|
|
378
|
+
-- ============================================================================
|
|
379
|
+
-- Schema version: 1.0.0
|
|
380
|
+
-- Compatible with: SQLite 3.35+, sqlite-vec (optional), sqlite-vss (optional)
|
|
381
|
+
-- WASM compatible: Yes (via SQLite-WASM + OPFS)
|
|
382
|
+
-- ============================================================================
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentdb",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.13",
|
|
4
4
|
"description": "AgentDB - Frontier Memory Features with MCP Integration: Causal reasoning, reflexion memory, skill library, and automated learning. 150x faster vector search. Full Claude Desktop support via Model Context Protocol.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
"./controllers/EmbeddingService": "./dist/controllers/EmbeddingService.js"
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
|
-
"build": "npm run build:ts && npm run build:browser",
|
|
24
|
+
"build": "npm run build:ts && npm run copy:schemas && npm run build:browser",
|
|
25
25
|
"build:ts": "tsc",
|
|
26
|
+
"copy:schemas": "mkdir -p dist/schemas && cp src/schemas/*.sql dist/schemas/",
|
|
26
27
|
"build:browser": "node scripts/build-browser.js",
|
|
27
28
|
"postinstall": "node scripts/postinstall.cjs || true",
|
|
28
29
|
"dev": "tsx src/cli/agentdb-cli.ts",
|
|
@@ -65,9 +66,9 @@
|
|
|
65
66
|
"dependencies": {
|
|
66
67
|
"@modelcontextprotocol/sdk": "^1.20.1",
|
|
67
68
|
"@xenova/transformers": "^2.17.2",
|
|
68
|
-
"better-sqlite3": "^11.7.0",
|
|
69
69
|
"chalk": "^5.3.0",
|
|
70
70
|
"commander": "^12.1.0",
|
|
71
|
+
"sql.js": "^1.13.0",
|
|
71
72
|
"zod": "^3.25.76"
|
|
72
73
|
},
|
|
73
74
|
"devDependencies": {
|
|
@@ -89,6 +90,6 @@
|
|
|
89
90
|
"LICENSE"
|
|
90
91
|
],
|
|
91
92
|
"optionalDependencies": {
|
|
92
|
-
"
|
|
93
|
+
"better-sqlite3": "^11.7.0"
|
|
93
94
|
}
|
|
94
95
|
}
|
package/src/cli/agentdb-cli.ts
CHANGED
|
@@ -63,11 +63,44 @@ class AgentDBCLI {
|
|
|
63
63
|
this.db.pragma('synchronous = NORMAL');
|
|
64
64
|
this.db.pragma('cache_size = -64000');
|
|
65
65
|
|
|
66
|
-
// Load schema
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
// Load both schemas: main schema (episodes, skills) + frontier schema (causal)
|
|
67
|
+
const schemaFiles = ['schema.sql', 'frontier-schema.sql'];
|
|
68
|
+
const basePaths = [
|
|
69
|
+
path.join(__dirname, '../schemas'), // dist/cli/../schemas
|
|
70
|
+
path.join(__dirname, '../../src/schemas'), // dist/cli/../../src/schemas
|
|
71
|
+
path.join(process.cwd(), 'dist/schemas'), // current/dist/schemas
|
|
72
|
+
path.join(process.cwd(), 'src/schemas'), // current/src/schemas
|
|
73
|
+
path.join(process.cwd(), 'node_modules/agentdb/dist/schemas') // installed package
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
let schemasLoaded = 0;
|
|
77
|
+
for (const basePath of basePaths) {
|
|
78
|
+
if (fs.existsSync(basePath)) {
|
|
79
|
+
for (const schemaFile of schemaFiles) {
|
|
80
|
+
const schemaPath = path.join(basePath, schemaFile);
|
|
81
|
+
if (fs.existsSync(schemaPath)) {
|
|
82
|
+
try {
|
|
83
|
+
const schema = fs.readFileSync(schemaPath, 'utf-8');
|
|
84
|
+
this.db.exec(schema);
|
|
85
|
+
schemasLoaded++;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
log.error(`Failed to load schema from ${schemaPath}: ${(error as Error).message}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// If we found at least one schema in this path, we're done
|
|
92
|
+
if (schemasLoaded > 0) break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (schemasLoaded === 0) {
|
|
97
|
+
log.warning('Schema files not found, database may not be initialized properly');
|
|
98
|
+
log.info('__dirname: ' + __dirname);
|
|
99
|
+
log.info('process.cwd(): ' + process.cwd());
|
|
100
|
+
log.info('Tried base paths:');
|
|
101
|
+
basePaths.forEach(p => {
|
|
102
|
+
log.info(` - ${p} (exists: ${fs.existsSync(p)})`);
|
|
103
|
+
});
|
|
71
104
|
}
|
|
72
105
|
|
|
73
106
|
// Initialize embedding service
|
|
@@ -656,13 +689,20 @@ async function main() {
|
|
|
656
689
|
process.exit(0);
|
|
657
690
|
}
|
|
658
691
|
|
|
692
|
+
const command = args[0];
|
|
693
|
+
|
|
694
|
+
// Handle MCP server command separately (doesn't need CLI initialization)
|
|
695
|
+
if (command === 'mcp') {
|
|
696
|
+
await handleMcpCommand(args.slice(1));
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
|
|
659
700
|
const cli = new AgentDBCLI();
|
|
660
701
|
const dbPath = process.env.AGENTDB_PATH || './agentdb.db';
|
|
661
702
|
|
|
662
703
|
try {
|
|
663
704
|
await cli.initialize(dbPath);
|
|
664
705
|
|
|
665
|
-
const command = args[0];
|
|
666
706
|
const subcommand = args[1];
|
|
667
707
|
|
|
668
708
|
if (command === 'causal') {
|
|
@@ -689,6 +729,35 @@ async function main() {
|
|
|
689
729
|
}
|
|
690
730
|
|
|
691
731
|
// Command handlers
|
|
732
|
+
async function handleMcpCommand(args: string[]) {
|
|
733
|
+
const subcommand = args[0];
|
|
734
|
+
|
|
735
|
+
if (subcommand === 'start' || !subcommand) {
|
|
736
|
+
log.info('Starting AgentDB MCP Server...');
|
|
737
|
+
|
|
738
|
+
// Dynamically import and run the MCP server
|
|
739
|
+
const mcpServerPath = path.join(__dirname, '../mcp/agentdb-mcp-server.js');
|
|
740
|
+
|
|
741
|
+
if (!fs.existsSync(mcpServerPath)) {
|
|
742
|
+
log.error('MCP server not found. Please rebuild the package: npm run build');
|
|
743
|
+
process.exit(1);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// Import and execute the MCP server module
|
|
747
|
+
try {
|
|
748
|
+
await import(mcpServerPath);
|
|
749
|
+
// The MCP server will run indefinitely, so we don't exit here
|
|
750
|
+
} catch (error) {
|
|
751
|
+
log.error(`Failed to start MCP server: ${(error as Error).message}`);
|
|
752
|
+
process.exit(1);
|
|
753
|
+
}
|
|
754
|
+
} else {
|
|
755
|
+
log.error(`Unknown mcp subcommand: ${subcommand}`);
|
|
756
|
+
log.info('Usage: agentdb mcp start');
|
|
757
|
+
process.exit(1);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
692
761
|
async function handleCausalCommands(cli: AgentDBCLI, subcommand: string, args: string[]) {
|
|
693
762
|
if (subcommand === 'add-edge') {
|
|
694
763
|
await cli.causalAddEdge({
|
|
@@ -849,6 +918,10 @@ ${colors.bright}${colors.cyan}AgentDB CLI - Frontier Memory Features${colors.res
|
|
|
849
918
|
${colors.bright}USAGE:${colors.reset}
|
|
850
919
|
agentdb <command> <subcommand> [options]
|
|
851
920
|
|
|
921
|
+
${colors.bright}MCP COMMANDS:${colors.reset}
|
|
922
|
+
agentdb mcp start
|
|
923
|
+
Start the MCP server for Claude Desktop integration
|
|
924
|
+
|
|
852
925
|
${colors.bright}CAUSAL COMMANDS:${colors.reset}
|
|
853
926
|
agentdb causal add-edge <cause> <effect> <uplift> [confidence] [sample-size]
|
|
854
927
|
Add a causal edge manually
|
package/src/db-fallback.ts
CHANGED
|
@@ -14,15 +14,20 @@ let dbImplementation: 'better-sqlite3' | 'sql.js' | null = null;
|
|
|
14
14
|
export async function getDatabaseImplementation(): Promise<typeof Database> {
|
|
15
15
|
// Return cached implementation
|
|
16
16
|
if (dbImplementation === 'better-sqlite3') {
|
|
17
|
-
|
|
17
|
+
const mod = await import('better-sqlite3');
|
|
18
|
+
return mod.default;
|
|
18
19
|
}
|
|
19
20
|
if (dbImplementation === 'sql.js') {
|
|
20
|
-
|
|
21
|
+
// sql.js requires async initialization, but we cached the wrapper
|
|
22
|
+
const mod = await import('sql.js');
|
|
23
|
+
const SQL = await mod.default();
|
|
24
|
+
return createSqlJsWrapper(SQL) as unknown as typeof Database;
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
// Try better-sqlite3 first (preferred)
|
|
24
28
|
try {
|
|
25
|
-
const
|
|
29
|
+
const mod = await import('better-sqlite3');
|
|
30
|
+
const BetterSqlite3 = mod.default;
|
|
26
31
|
|
|
27
32
|
// Test that it actually works
|
|
28
33
|
const testDb = new BetterSqlite3(':memory:');
|
|
@@ -40,8 +45,8 @@ export async function getDatabaseImplementation(): Promise<typeof Database> {
|
|
|
40
45
|
console.log('⚠️ Attempting sql.js fallback (slower but no compilation needed)...');
|
|
41
46
|
|
|
42
47
|
// sql.js requires async initialization
|
|
43
|
-
const
|
|
44
|
-
const SQL = await
|
|
48
|
+
const mod = await import('sql.js');
|
|
49
|
+
const SQL = await mod.default();
|
|
45
50
|
|
|
46
51
|
// Create better-sqlite3 compatible wrapper
|
|
47
52
|
const SqlJsWrapper = createSqlJsWrapper(SQL);
|
|
@@ -80,7 +85,7 @@ function createSqlJsWrapper(SQL: any) {
|
|
|
80
85
|
this.db = new SQL.Database();
|
|
81
86
|
} else {
|
|
82
87
|
// File-based database
|
|
83
|
-
const fs =
|
|
88
|
+
const fs = await import('fs');
|
|
84
89
|
if (fs.existsSync(filename)) {
|
|
85
90
|
const buffer = fs.readFileSync(filename);
|
|
86
91
|
this.db = new SQL.Database(buffer);
|
|
@@ -156,10 +161,10 @@ function createSqlJsWrapper(SQL: any) {
|
|
|
156
161
|
return this.db.exec(sql);
|
|
157
162
|
}
|
|
158
163
|
|
|
159
|
-
close() {
|
|
164
|
+
async close() {
|
|
160
165
|
// Save to file if needed
|
|
161
166
|
if (this.filename !== ':memory:') {
|
|
162
|
-
const fs =
|
|
167
|
+
const fs = await import('fs');
|
|
163
168
|
const data = this.db.export();
|
|
164
169
|
fs.writeFileSync(this.filename, Buffer.from(data));
|
|
165
170
|
}
|
|
@@ -174,6 +179,14 @@ function createSqlJsWrapper(SQL: any) {
|
|
|
174
179
|
};
|
|
175
180
|
}
|
|
176
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Create a database instance using the best available implementation
|
|
184
|
+
*/
|
|
185
|
+
export async function createDatabase(filename: string, options?: any): Promise<InstanceType<typeof Database>> {
|
|
186
|
+
const DatabaseImpl = await getDatabaseImplementation();
|
|
187
|
+
return new DatabaseImpl(filename, options) as InstanceType<typeof Database>;
|
|
188
|
+
}
|
|
189
|
+
|
|
177
190
|
/**
|
|
178
191
|
* Get information about current database implementation
|
|
179
192
|
*/
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
ListToolsRequestSchema,
|
|
13
13
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
14
14
|
import Database from 'better-sqlite3';
|
|
15
|
+
import { createDatabase } from '../db-fallback.js';
|
|
15
16
|
import { CausalMemoryGraph } from '../controllers/CausalMemoryGraph.js';
|
|
16
17
|
import { CausalRecall } from '../controllers/CausalRecall.js';
|
|
17
18
|
import { ReflexionMemory } from '../controllers/ReflexionMemory.js';
|
|
@@ -28,7 +29,7 @@ import * as fs from 'fs';
|
|
|
28
29
|
// Initialize AgentDB Controllers
|
|
29
30
|
// ============================================================================
|
|
30
31
|
const dbPath = process.env.AGENTDB_PATH || './agentdb.db';
|
|
31
|
-
const db =
|
|
32
|
+
const db = await createDatabase(dbPath);
|
|
32
33
|
|
|
33
34
|
// Configure for performance
|
|
34
35
|
db.pragma('journal_mode = WAL');
|