feat(storage): add SQLite wrapper and full schema migrations (15 tables)

This commit is contained in:
2026-06-10 00:48:44 +03:30
parent 57cfe4516f
commit d29b194f73
2 changed files with 161 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
package storage
var migrations = []string{
divacodeSchema,
companionSchema,
}
const divacodeSchema = `
CREATE TABLE IF NOT EXISTS conversations (
id TEXT PRIMARY KEY,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS messages (
id TEXT PRIMARY KEY,
conversation_id TEXT NOT NULL REFERENCES conversations(id),
role TEXT NOT NULL CHECK(role IN ('user','assistant','system','tool')),
content TEXT NOT NULL,
tool_call TEXT,
token_count INTEGER,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_messages_conversation ON messages(conversation_id);
CREATE TABLE IF NOT EXISTS context_state (
conversation_id TEXT PRIMARY KEY REFERENCES conversations(id),
token_count INTEGER NOT NULL DEFAULT 0,
summary TEXT
);
CREATE TABLE IF NOT EXISTS memories (
id TEXT PRIMARY KEY,
content TEXT NOT NULL,
embedding BLOB,
source TEXT,
importance REAL DEFAULT 0.5,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
last_accessed TEXT
);
CREATE INDEX IF NOT EXISTS idx_memories_importance ON memories(importance);
CREATE INDEX IF NOT EXISTS idx_memories_created ON memories(created_at);
`
const companionSchema = `
CREATE TABLE IF NOT EXISTS personality_traits (
id TEXT PRIMARY KEY,
trait TEXT NOT NULL UNIQUE,
value REAL NOT NULL DEFAULT 0.5,
min_value REAL NOT NULL DEFAULT 0.0,
max_value REAL NOT NULL DEFAULT 1.0,
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS relationship_metrics (
id TEXT PRIMARY KEY,
metric TEXT NOT NULL UNIQUE,
value REAL NOT NULL DEFAULT 0.0,
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS shared_topics (
id TEXT PRIMARY KEY,
topic TEXT NOT NULL UNIQUE,
count INTEGER NOT NULL DEFAULT 1,
last_discussed TEXT
);
CREATE TABLE IF NOT EXISTS inside_jokes (
id TEXT PRIMARY KEY,
joke TEXT NOT NULL,
context TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS diary_entries (
id TEXT PRIMARY KEY,
date TEXT NOT NULL,
summary TEXT NOT NULL,
mood TEXT,
topics TEXT,
observations TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS observations (
id TEXT PRIMARY KEY,
content TEXT NOT NULL,
confidence REAL DEFAULT 0.5,
category TEXT,
applied INTEGER DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS agent_promises (
id TEXT PRIMARY KEY,
promise TEXT NOT NULL,
context TEXT,
fulfilled INTEGER DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
deadline TEXT
);
CREATE TABLE IF NOT EXISTS agent_strategies (
id TEXT PRIMARY KEY,
situation TEXT NOT NULL,
strategy TEXT NOT NULL,
outcome TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
`

View File

@@ -0,0 +1,48 @@
package storage
import (
"database/sql"
_ "modernc.org/sqlite"
)
type DB struct {
*sql.DB
}
func Open(path string) (*DB, error) {
db, err := sql.Open("sqlite", path+"?_pragma=journal_mode(WAL)&_pragma=busy_timeout(5000)&_pragma=foreign_keys(1)")
if err != nil {
return nil, err
}
if err := db.Ping(); err != nil {
return nil, err
}
return &DB{db}, nil
}
func (db *DB) Migrate() error {
for _, m := range migrations {
if err := db.Exec(m); err != nil {
return err
}
}
return nil
}
func (db *DB) Exec(query string, args ...interface{}) error {
_, err := db.DB.Exec(query, args...)
return err
}
func (db *DB) Query(query string, args ...interface{}) (*sql.Rows, error) {
return db.DB.Query(query, args...)
}
func (db *DB) QueryRow(query string, args ...interface{}) *sql.Row {
return db.DB.QueryRow(query, args...)
}
func (db *DB) Close() error {
return db.DB.Close()
}