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:
@@ -0,0 +1,22 @@
|
|||||||
|
-- Memoria persistente del agente: facts (clave/valor por sujeto) + messages (historial chat).
|
||||||
|
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
|
||||||
|
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);
|
||||||
+27
-22
@@ -4,38 +4,43 @@ package shellmem
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/enmanuel/agents/pkg/llm"
|
"github.com/enmanuel/agents/pkg/llm"
|
||||||
"github.com/enmanuel/agents/pkg/memory"
|
"github.com/enmanuel/agents/pkg/memory"
|
||||||
)
|
)
|
||||||
|
|
||||||
const schema = `
|
//go:embed migrations/*.sql
|
||||||
CREATE TABLE IF NOT EXISTS facts (
|
var migrationsFS embed.FS
|
||||||
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)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS messages (
|
func applyMigrations(db *sql.DB) error {
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
files, err := fs.Glob(migrationsFS, "migrations/*.sql")
|
||||||
agent_id TEXT NOT NULL,
|
if err != nil {
|
||||||
room_id TEXT NOT NULL,
|
return err
|
||||||
role TEXT NOT NULL,
|
}
|
||||||
content TEXT NOT NULL,
|
sort.Strings(files)
|
||||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
for _, f := range files {
|
||||||
);
|
b, err := migrationsFS.ReadFile(f)
|
||||||
|
if err != nil {
|
||||||
CREATE INDEX IF NOT EXISTS idx_messages_room ON messages(agent_id, room_id, created_at DESC);
|
return err
|
||||||
CREATE INDEX IF NOT EXISTS idx_facts_subject ON facts(agent_id, subject);
|
}
|
||||||
`
|
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.
|
// SQLiteStore implements memory.Store using SQLite.
|
||||||
type SQLiteStore struct {
|
type SQLiteStore struct {
|
||||||
@@ -54,7 +59,7 @@ func New(dbPath string, logger *slog.Logger) (*SQLiteStore, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("open memory db: %w", err)
|
return nil, fmt.Errorf("open memory db: %w", err)
|
||||||
}
|
}
|
||||||
if _, err := db.Exec(schema); err != nil {
|
if err := applyMigrations(db); err != nil {
|
||||||
db.Close()
|
db.Close()
|
||||||
return nil, fmt.Errorf("migrate memory db: %w", err)
|
return nil, fmt.Errorf("migrate memory db: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user