use basemyai_core::Migration;
pub const EMBEDDING_DIM: usize = 384;
pub const BMAI_FORMAT_VERSION: u32 = 1;
const BMAI_META_SCHEMA_V5: &str = "\
CREATE TABLE IF NOT EXISTS bmai_meta (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
INSERT OR IGNORE INTO bmai_meta (key, value) VALUES
('format', 'basemyai-memory'),
('format_version', '1'),
('storage_engine', 'libsql'),
('schema_family', 'agent-memory'),
('embedding_dim', '384');
";
const MEMORY_SCHEMA_V1: &str = "\
CREATE TABLE IF NOT EXISTS memory (
id TEXT PRIMARY KEY,
agent_id TEXT NOT NULL,
layer TEXT NOT NULL,
content TEXT NOT NULL,
valid_from INTEGER NOT NULL,
valid_until INTEGER,
emb F32_BLOB(384)
);
CREATE INDEX IF NOT EXISTS memory_idx ON memory(libsql_vector_idx(emb, 'metric=cosine'));
";
const GRAPH_SCHEMA_V2: &str = "\
CREATE TABLE IF NOT EXISTS entity (
agent_id TEXT NOT NULL,
id TEXT NOT NULL,
kind TEXT NOT NULL,
label TEXT NOT NULL,
valid_from INTEGER NOT NULL,
valid_until INTEGER,
importance REAL NOT NULL DEFAULT 0,
PRIMARY KEY (agent_id, id)
);
CREATE INDEX IF NOT EXISTS entity_agent_idx ON entity(agent_id);
CREATE TABLE IF NOT EXISTS edge (
agent_id TEXT NOT NULL,
src TEXT NOT NULL,
dst TEXT NOT NULL,
relation TEXT NOT NULL,
weight REAL NOT NULL DEFAULT 1,
valid_from INTEGER NOT NULL,
valid_until INTEGER,
PRIMARY KEY (agent_id, src, dst, relation)
);
CREATE INDEX IF NOT EXISTS edge_src_idx ON edge(agent_id, src);
";
const GRAPH_AGENT_SCOPED_KEYS_V6: &str = "\
CREATE TABLE IF NOT EXISTS entity_v6 (
agent_id TEXT NOT NULL,
id TEXT NOT NULL,
kind TEXT NOT NULL,
label TEXT NOT NULL,
valid_from INTEGER NOT NULL,
valid_until INTEGER,
importance REAL NOT NULL DEFAULT 0,
PRIMARY KEY (agent_id, id)
);
INSERT OR IGNORE INTO entity_v6 (agent_id, id, kind, label, valid_from, valid_until, importance)
SELECT agent_id, id, kind, label, valid_from, valid_until, importance FROM entity;
DROP TABLE entity;
ALTER TABLE entity_v6 RENAME TO entity;
CREATE INDEX IF NOT EXISTS entity_agent_idx ON entity(agent_id);
CREATE TABLE IF NOT EXISTS edge_v6 (
agent_id TEXT NOT NULL,
src TEXT NOT NULL,
dst TEXT NOT NULL,
relation TEXT NOT NULL,
weight REAL NOT NULL DEFAULT 1,
valid_from INTEGER NOT NULL,
valid_until INTEGER,
PRIMARY KEY (agent_id, src, dst, relation)
);
INSERT OR IGNORE INTO edge_v6 (agent_id, src, dst, relation, weight, valid_from, valid_until)
SELECT agent_id, src, dst, relation, weight, valid_from, valid_until FROM edge;
DROP TABLE edge;
ALTER TABLE edge_v6 RENAME TO edge;
CREATE INDEX IF NOT EXISTS edge_src_idx ON edge(agent_id, src);
";
const MEMORY_FTS_SCHEMA_V4: &str = "\
CREATE VIRTUAL TABLE IF NOT EXISTS memory_fts USING fts5(
id UNINDEXED,
agent_id UNINDEXED,
content,
tokenize = 'porter unicode61 remove_diacritics 2'
);
INSERT INTO memory_fts (id, agent_id, content)
SELECT id, agent_id, content FROM memory;
";
const MEMORY_SCHEMA_V3: &str = "\
ALTER TABLE memory ADD COLUMN importance REAL NOT NULL DEFAULT 0;
ALTER TABLE memory ADD COLUMN last_access INTEGER;
";
const MEMORY_SCHEMA_V7: &str = "\
ALTER TABLE memory ADD COLUMN source TEXT NOT NULL DEFAULT 'user';
";
#[must_use]
pub fn schema() -> Vec<Migration> {
vec![
Migration {
version: 1,
up_sql: MEMORY_SCHEMA_V1,
},
Migration {
version: 2,
up_sql: GRAPH_SCHEMA_V2,
},
Migration {
version: 3,
up_sql: MEMORY_SCHEMA_V3,
},
Migration {
version: 4,
up_sql: MEMORY_FTS_SCHEMA_V4,
},
Migration {
version: 5,
up_sql: BMAI_META_SCHEMA_V5,
},
Migration {
version: 6,
up_sql: GRAPH_AGENT_SCOPED_KEYS_V6,
},
Migration {
version: 7,
up_sql: MEMORY_SCHEMA_V7,
},
]
}