refactor(memory): migration files + embed.FS
- shell/memory/migrations/001_init.sql extraido del schema inline - sqlite.go: applyMigrations() con embed.FS aplicado al abrir - aplica regla db_migrations.md (fn_registry/.claude/rules/) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+27
-22
@@ -4,38 +4,43 @@ package shellmem
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"embed"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/enmanuel/agents/pkg/llm"
|
||||
"github.com/enmanuel/agents/pkg/memory"
|
||||
)
|
||||
|
||||
const schema = `
|
||||
CREATE TABLE IF NOT EXISTS facts (
|
||||
agent_id TEXT NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
key TEXT NOT NULL,
|
||||
value TEXT NOT NULL,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (agent_id, subject, key)
|
||||
);
|
||||
//go:embed migrations/*.sql
|
||||
var migrationsFS embed.FS
|
||||
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
agent_id TEXT NOT NULL,
|
||||
room_id TEXT NOT NULL,
|
||||
role TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_room ON messages(agent_id, room_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_facts_subject ON facts(agent_id, subject);
|
||||
`
|
||||
func applyMigrations(db *sql.DB) error {
|
||||
files, err := fs.Glob(migrationsFS, "migrations/*.sql")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.Strings(files)
|
||||
for _, f := range files {
|
||||
b, err := migrationsFS.ReadFile(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := db.Exec(string(b)); err != nil {
|
||||
if strings.Contains(err.Error(), "duplicate column") || strings.Contains(err.Error(), "already exists") {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("migrate %s: %w", f, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SQLiteStore implements memory.Store using SQLite.
|
||||
type SQLiteStore struct {
|
||||
@@ -54,7 +59,7 @@ func New(dbPath string, logger *slog.Logger) (*SQLiteStore, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open memory db: %w", err)
|
||||
}
|
||||
if _, err := db.Exec(schema); err != nil {
|
||||
if err := applyMigrations(db); err != nil {
|
||||
db.Close()
|
||||
return nil, fmt.Errorf("migrate memory db: %w", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user