feat(storage): add SQLite wrapper and full schema migrations (15 tables)
This commit is contained in:
113
internal/storage/migrations.go
Normal file
113
internal/storage/migrations.go
Normal 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'))
|
||||||
|
);
|
||||||
|
`
|
||||||
48
internal/storage/sqlite.go
Normal file
48
internal/storage/sqlite.go
Normal 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()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user