Commit rest of changes
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -15,6 +15,10 @@
|
|||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
*.out
|
*.out
|
||||||
|
|
||||||
|
# Backup files
|
||||||
|
*.bak
|
||||||
|
|
||||||
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
# Dependency directories (remove the comment below to include it)
|
||||||
# vendor/
|
# vendor/
|
||||||
|
|
||||||
|
36
internal/storage/migrations/001_initial.sql
Normal file
36
internal/storage/migrations/001_initial.sql
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
-- sessions table stores high-level chat session metadata.
|
||||||
|
CREATE TABLE IF NOT EXISTS sessions (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
model_name TEXT NOT NULL,
|
||||||
|
summary TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_sessions_name ON sessions(name);
|
||||||
|
|
||||||
|
-- messages table stores individual conversation messages linked to sessions.
|
||||||
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
session_id INTEGER NOT NULL,
|
||||||
|
role TEXT NOT NULL,
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
token_count INTEGER,
|
||||||
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY(session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_messages_session_created_at ON messages(session_id, created_at);
|
||||||
|
|
||||||
|
-- models table tracks available models and usage metadata.
|
||||||
|
CREATE TABLE IF NOT EXISTS models (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
display_name TEXT,
|
||||||
|
provider TEXT,
|
||||||
|
is_default BOOLEAN NOT NULL DEFAULT 0,
|
||||||
|
last_used_at DATETIME
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_models_name ON models(name);
|
@@ -4,9 +4,11 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -57,6 +59,11 @@ func (m *Manager) Open() (*sql.DB, error) {
|
|||||||
return nil, fmt.Errorf("ping sqlite: %w", err)
|
return nil, fmt.Errorf("ping sqlite: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := applyMigrations(db); err != nil {
|
||||||
|
_ = db.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
m.db = db
|
m.db = db
|
||||||
return db, nil
|
return db, nil
|
||||||
}
|
}
|
||||||
@@ -112,3 +119,49 @@ func ensureDir(dir string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyMigrations(db *sql.DB) error {
|
||||||
|
migrationsFS := os.DirFS("internal/storage/migrations")
|
||||||
|
|
||||||
|
entries, err := fs.ReadDir(migrationsFS, ".")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read migrations: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var files []string
|
||||||
|
for _, entry := range entries {
|
||||||
|
if entry.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if filepath.Ext(entry.Name()) != ".sql" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
files = append(files, entry.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(files)
|
||||||
|
|
||||||
|
tx, err := db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("begin migration tx: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range files {
|
||||||
|
data, readErr := fs.ReadFile(migrationsFS, name)
|
||||||
|
if readErr != nil {
|
||||||
|
_ = tx.Rollback()
|
||||||
|
return fmt.Errorf("read migration %s: %w", name, readErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, execErr := tx.Exec(string(data)); execErr != nil {
|
||||||
|
_ = tx.Rollback()
|
||||||
|
return fmt.Errorf("apply migration %s: %w", name, execErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return fmt.Errorf("commit migrations: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user