Documentation
¶
Overview ¶
Package db es la capa de persistencia de nem: modelos GORM sobre SQLite (glebarez/sqlite, Go puro, sin cgo) más una capa FTS5 en SQL crudo para búsqueda full-text con ranking BM25.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Chat ¶
type Chat struct {
ID string `gorm:"primaryKey"`
Title string
Source string `gorm:"index"` // "codex" | "claude" | "manual"
CreatedAt int64 // unix seconds, autocompletado por GORM
SessionPath string
Messages []Message `gorm:"foreignKey:ChatID;constraint:OnDelete:CASCADE"`
}
Chat representa una conversación ingestada desde un agente (codex, claude) o creada manualmente. Es el contenedor de mensajes y commits.
type Commit ¶
type Commit struct {
Hash string `gorm:"primaryKey"`
ChatID string `gorm:"index"`
Branch string `gorm:"default:main"`
Message string // mensaje del commit, escrito por el agente o el humano
MsgFrom string // id del primer mensaje del rango
MsgTo string // id del último mensaje del rango
Snapshot string // JSON con el texto copiado de los mensajes (inmutable)
CreatedAt int64
}
Commit es un snapshot INMUTABLE de un rango de mensajes. Copia el texto en Snapshot (JSON) al momento de commitear, de modo que reingestar o editar mensajes nunca altera lo que un commit ya capturó: "tu agente olvida, nem no".
type Config ¶
type Config struct {
// contains filtered or unexported fields
}
Config contiene la configuración para abrir un Store.
type Embedding ¶ added in v0.2.0
type Embedding struct {
NodeID string `gorm:"primaryKey"`
Dim int
Vec []byte // float32 little-endian (ver internal/embed.Encode)
}
Embedding es el vector (opcional) de un nodo del índice, guardado como BLOB float32. Capa semántica apagada por default; se llena con `nem index` cuando hay un backend de embeddings configurado.
type Memory ¶
type Memory struct {
ID string `gorm:"primaryKey"`
ChatID string `gorm:"index"`
Content string
CommitHash string // commit que respalda este recuerdo (evidencia)
CreatedAt int64
UpdatedAt int64
}
Memory es la capa MUTABLE sobre el registro inmutable: un hecho/decisión destilado que el agente lee al empezar una sesión. Puede actualizarse, y referencia el commit que lo respalda como evidencia.
type Message ¶
type Message struct {
ID string `gorm:"primaryKey"`
ChatID string `gorm:"index"`
Role string // "user" | "assistant" | "tool" | "system"
Content string
Timestamp int64
TokenCount int
Seq int64 `gorm:"index"` // orden dentro del chat
}
Message es un turno individual dentro de un chat. El campo Seq da orden determinístico dentro del chat (los timestamps pueden colisionar).
type Node ¶ added in v0.2.0
type Node struct {
ID string `gorm:"primaryKey"`
ParentID string `gorm:"index"` // padre en el árbol ("" para root)
Kind string `gorm:"index"` // root|project|chat|commit|segment
ChatID string `gorm:"index"` // chat dueño (chat/commit/segment)
Title string //
Summary string // lo que el agente lee para navegar
MsgFromSeq int64 // rango cubierto (drill-down)
MsgToSeq int64 //
CommitHash string // si Kind==commit
CreatedAt int64 `gorm:"index"` // tiempo de la fuente (orden temporal); se setea explícito
Tokens int // tamaño aprox. del contenido (para presupuestar)
Superseded bool // la decisión fue reemplazada por una posterior
SupersededBy string // id del nodo/commit que la reemplaza
Pinned bool `gorm:"index"` // resumen escrito por el agente/humano; `index` nunca lo auto-pisa (capa mutable sobre los commits inmutables)
// Duraciones (capa temporal): tiempo activo real vs span de calendario, para
// que el agente calibre estimaciones. Se computan en `index` desde los
// timestamps de los mensajes (ver internal/timing).
ActiveSecs int64 // tiempo activo (segundos), modelo role-aware
WallSecs int64 // span de calendario (último - primer mensaje), segundos
Sessions int // nº de "sesiones" (sentadas separadas por huecos largos)
LastActive int64 // unix del último mensaje (para recencia)
}
Node es un nodo del árbol de índice (estilo PageIndex) que el agente navega: root → project → chat → commit (→ segment). El Summary es lo que el agente lee para decidir en qué rama bajar; el rango [MsgFromSeq, MsgToSeq] permite el drill-down al contenido real. Es el equivalente a una "tabla de contenidos" de todo el historial, sin embeddings.
type NodeHit ¶ added in v0.2.0
NodeHit es un resultado de búsqueda sobre el árbol: el nodo más su score BM25.
type Option ¶
Option configura la apertura de un Store.
func WithVerbose ¶
WithVerbose habilita el logging de queries de GORM (debug).
type SearchHit ¶
SearchHit es un resultado de búsqueda: el mensaje más metadata del chat y el score BM25 (menor = más relevante).
type Staging ¶
type Staging struct {
ID string `gorm:"primaryKey"`
ChatID string `gorm:"index;uniqueIndex:idx_staging_chat_msg"`
MsgID string `gorm:"uniqueIndex:idx_staging_chat_msg"`
Seq int64 // copia del Seq del mensaje para ordenar el rango
CreatedAt int64
}
Staging es el index git-like: los mensajes marcados con `nem add` que esperan ser commiteados. Una fila por mensaje staged del chat activo.
type Stamp ¶ added in v0.3.0
Stamp es el par (rol, timestamp) de un mensaje, para medir duraciones sin cargar el contenido completo.
type Store ¶
type Store interface {
// Migrate aplica el esquema (modelos + FTS5). Es idempotente.
Migrate() error
// Close libera la conexión subyacente.
Close() error
// UpsertChat inserta el chat o actualiza su metadata si ya existe.
UpsertChat(chat *Chat) error
// InsertMessages inserta mensajes ignorando los que ya existen (por id).
// Devuelve cuántos se insertaron realmente (idempotente).
InsertMessages(msgs []Message) (int64, error)
// CountMessages cuenta los mensajes de un chat.
CountMessages(chatID string) (int64, error)
// LastMessages devuelve los últimos n mensajes del chat por orden Seq,
// filtrando por roles (vacío/nil = todos). El filtro se aplica ANTES del
// límite: "los últimos n de los roles elegidos".
LastMessages(chatID string, n int, roles []string) ([]Message, error)
// GetChat devuelve un chat por id (nil, nil si no existe).
GetChat(id string) (*Chat, error)
// ListChats devuelve todos los chats (para resolver scopes).
ListChats() ([]Chat, error)
// MessageByID devuelve un mensaje por id dentro de un chat.
MessageByID(chatID, msgID string) (*Message, error)
// MessagesBySeqRange devuelve los mensajes del chat con Seq en [from,to],
// filtrando por roles (vacío/nil = todos).
MessagesBySeqRange(chatID string, fromSeq, toSeq int64, roles []string) ([]Message, error)
// MessageStamps devuelve los (rol, timestamp) válidos del chat en orden de Seq
// (para medir duración activa sin cargar el contenido).
MessageStamps(chatID string) ([]Stamp, error)
// SearchMessages busca full-text (FTS5/BM25) y devuelve los mejores hits.
// roles filtra por rol de mensaje; chatIDs limita a esos chats (scope).
// Ambos vacíos/nil = sin filtro.
SearchMessages(query string, limit int, roles, chatIDs []string) ([]SearchHit, error)
// StageMessages agrega mensajes al staging del chat (idempotente por msg).
// Devuelve cuántos quedaron staged nuevos.
StageMessages(chatID string, msgs []Message) (int64, error)
// StagedMessages devuelve los mensajes staged del chat, ordenados por Seq.
StagedMessages(chatID string) ([]Message, error)
// CountStaged cuenta los mensajes staged del chat.
CountStaged(chatID string) (int64, error)
// ClearStaging vacía el staging del chat.
ClearStaging(chatID string) error
// CreateCommit persiste un commit inmutable.
CreateCommit(c *Commit) error
// HeadCommit devuelve el commit más reciente del chat (nil si no hay).
HeadCommit(chatID string) (*Commit, error)
// GetCommit devuelve un commit por hash (acepta prefijo único).
GetCommit(hash string) (*Commit, error)
// ListCommits lista los commits del chat, del más nuevo al más viejo.
ListCommits(chatID string) ([]Commit, error)
// ListAllCommits lista todos los commits (para exportar en sync).
ListAllCommits() ([]Commit, error)
// --- árbol de índice (nodes) ---
// ClearNodes borra todo el árbol (para un rebuild completo de `nem index`).
ClearNodes() error
// UpsertNodes inserta o actualiza nodos por id. Devuelve cuántos escribió.
UpsertNodes(nodes []Node) (int64, error)
// GetNode devuelve un nodo por id (nil, nil si no existe).
GetNode(id string) (*Node, error)
// SetNodeSummary reescribe el resumen de un nodo y lo marca Pinned (escrito a
// mano por el agente/humano), de modo que `nem index` no lo regenere.
SetNodeSummary(id, summary string) error
// PinnedNodes devuelve los nodos con resumen Pinned (para respetarlos en Build).
PinnedNodes() ([]Node, error)
// ChildNodes devuelve los hijos directos de un nodo (orden por CreatedAt).
ChildNodes(parentID string) ([]Node, error)
// RootNodes devuelve los nodos raíz (ParentID == "").
RootNodes() ([]Node, error)
// CountNodes cuenta los nodos del árbol.
CountNodes() (int64, error)
// SearchNodes busca full-text (FTS5/BM25) sobre title+summary de los nodos.
// chatIDs limita a esos chats (scope); vacío/nil = sin filtro.
SearchNodes(query string, limit int, chatIDs []string) ([]NodeHit, error)
// CommitNodes devuelve los nodos de commit de los chats dados, ordenados por
// CreatedAt ascendente (para la vista temporal `nem timeline`). chatIDs
// vacío/nil = todos.
CommitNodes(chatIDs []string) ([]Node, error)
// --- embeddings (capa opcional) ---
// ClearEmbeddings borra todos los vectores.
ClearEmbeddings() error
// UpsertEmbeddings inserta/actualiza vectores por NodeID.
UpsertEmbeddings(embs []Embedding) (int64, error)
// AllEmbeddings devuelve todos los vectores guardados.
AllEmbeddings() ([]Embedding, error)
}
Store es la interface de acceso a datos de nem. Toda la app depende de esta abstracción, no de GORM directamente, para que los comandos sean testeables con un mock.