store

package
v1.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 7, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package store implements the persistent memory engine for Engram.

It uses SQLite with FTS5 full-text search to store and retrieve observations from AI coding sessions. This is the core of Engram — everything else (HTTP server, MCP server, CLI, plugins) talks to this.

Index

Constants

View Source
const (
	DefaultSyncTargetKey = "cloud"

	SyncLifecycleIdle     = "idle"
	SyncLifecyclePending  = "pending"
	SyncLifecycleRunning  = "running"
	SyncLifecycleHealthy  = "healthy"
	SyncLifecycleDegraded = "degraded"

	SyncEntitySession     = "session"
	SyncEntityObservation = "observation"
	SyncEntityPrompt      = "prompt"

	SyncOpUpsert = "upsert"
	SyncOpDelete = "delete"

	SyncSourceLocal  = "local"
	SyncSourceRemote = "remote"
)

Variables

This section is empty.

Functions

func ClassifyTool

func ClassifyTool(toolName string) string

ClassifyTool returns the observation type for a given tool name.

func ExtractLearnings

func ExtractLearnings(text string) []string

ExtractLearnings parses structured learning items from text. It looks for sections like "## Key Learnings:" or "## Aprendizajes Clave:" and extracts numbered (1. text) or bullet (- text) items. Returns learnings from the LAST matching section (most recent output).

func Now

func Now() string

Now returns the current time formatted for SQLite.

func SuggestTopicKey

func SuggestTopicKey(typ, title, content string) string

SuggestTopicKey generates a stable topic key suggestion from type/title/content. It infers a topic family (e.g. architecture/*, bug/*) and then appends a normalized segment from title/content for stable cross-session keys.

Types

type AddObservationParams

type AddObservationParams struct {
	SessionID string `json:"session_id"`
	Type      string `json:"type"`
	Title     string `json:"title"`
	Content   string `json:"content"`
	ToolName  string `json:"tool_name,omitempty"`
	Project   string `json:"project,omitempty"`
	Scope     string `json:"scope,omitempty"`
	TopicKey  string `json:"topic_key,omitempty"`
}

type AddPromptParams

type AddPromptParams struct {
	SessionID string `json:"session_id"`
	Content   string `json:"content"`
	Project   string `json:"project,omitempty"`
}

type Config

type Config struct {
	DataDir              string
	MaxObservationLength int
	MaxContextResults    int
	MaxSearchResults     int
	DedupeWindow         time.Duration
}

func DefaultConfig

func DefaultConfig() Config

type EnrolledProject added in v1.8.0

type EnrolledProject struct {
	Project    string `json:"project"`
	EnrolledAt string `json:"enrolled_at"`
}

EnrolledProject represents a project enrolled for cloud sync.

type ExportData

type ExportData struct {
	Version      string        `json:"version"`
	ExportedAt   string        `json:"exported_at"`
	Sessions     []Session     `json:"sessions"`
	Observations []Observation `json:"observations"`
	Prompts      []Prompt      `json:"prompts"`
}

ExportData is the full serializable dump of the engram database.

type ImportResult

type ImportResult struct {
	SessionsImported     int `json:"sessions_imported"`
	ObservationsImported int `json:"observations_imported"`
	PromptsImported      int `json:"prompts_imported"`
}

type Observation

type Observation struct {
	ID             int64   `json:"id"`
	SyncID         string  `json:"sync_id"`
	SessionID      string  `json:"session_id"`
	Type           string  `json:"type"`
	Title          string  `json:"title"`
	Content        string  `json:"content"`
	ToolName       *string `json:"tool_name,omitempty"`
	Project        *string `json:"project,omitempty"`
	Scope          string  `json:"scope"`
	TopicKey       *string `json:"topic_key,omitempty"`
	RevisionCount  int     `json:"revision_count"`
	DuplicateCount int     `json:"duplicate_count"`
	LastSeenAt     *string `json:"last_seen_at,omitempty"`
	CreatedAt      string  `json:"created_at"`
	UpdatedAt      string  `json:"updated_at"`
	DeletedAt      *string `json:"deleted_at,omitempty"`
}

type PassiveCaptureParams

type PassiveCaptureParams struct {
	SessionID string `json:"session_id"`
	Content   string `json:"content"`
	Project   string `json:"project,omitempty"`
	Source    string `json:"source,omitempty"` // e.g. "subagent-stop", "session-end"
}

PassiveCaptureParams holds the input for passive memory capture.

type PassiveCaptureResult

type PassiveCaptureResult struct {
	Extracted  int `json:"extracted"`  // Total learnings found in text
	Saved      int `json:"saved"`      // New observations created
	Duplicates int `json:"duplicates"` // Skipped because already existed
}

PassiveCaptureResult holds the output of passive memory capture.

type Prompt

type Prompt struct {
	ID        int64  `json:"id"`
	SyncID    string `json:"sync_id"`
	SessionID string `json:"session_id"`
	Content   string `json:"content"`
	Project   string `json:"project,omitempty"`
	CreatedAt string `json:"created_at"`
}

type SearchOptions

type SearchOptions struct {
	Type    string `json:"type,omitempty"`
	Project string `json:"project,omitempty"`
	Scope   string `json:"scope,omitempty"`
	Limit   int    `json:"limit,omitempty"`
}

type SearchResult

type SearchResult struct {
	Observation
	Rank float64 `json:"rank"`
}

type Session

type Session struct {
	ID        string  `json:"id"`
	Project   string  `json:"project"`
	Directory string  `json:"directory"`
	StartedAt string  `json:"started_at"`
	EndedAt   *string `json:"ended_at,omitempty"`
	Summary   *string `json:"summary,omitempty"`
}

type SessionSummary

type SessionSummary struct {
	ID               string  `json:"id"`
	Project          string  `json:"project"`
	StartedAt        string  `json:"started_at"`
	EndedAt          *string `json:"ended_at,omitempty"`
	Summary          *string `json:"summary,omitempty"`
	ObservationCount int     `json:"observation_count"`
}

type Stats

type Stats struct {
	TotalSessions     int      `json:"total_sessions"`
	TotalObservations int      `json:"total_observations"`
	TotalPrompts      int      `json:"total_prompts"`
	Projects          []string `json:"projects"`
}

type Store

type Store struct {
	// contains filtered or unexported fields
}

func New

func New(cfg Config) (*Store, error)

func (*Store) AckSyncMutationSeqs added in v1.8.0

func (s *Store) AckSyncMutationSeqs(targetKey string, seqs []int64) error

AckSyncMutationSeqs acknowledges specific mutation sequence numbers without requiring them to be contiguous.

func (*Store) AckSyncMutations added in v1.8.0

func (s *Store) AckSyncMutations(targetKey string, lastAckedSeq int64) error

func (*Store) AcquireSyncLease added in v1.8.0

func (s *Store) AcquireSyncLease(targetKey, owner string, ttl time.Duration, now time.Time) (bool, error)

func (*Store) AddObservation

func (s *Store) AddObservation(p AddObservationParams) (int64, error)

func (*Store) AddPrompt

func (s *Store) AddPrompt(p AddPromptParams) (int64, error)

func (*Store) AllObservations

func (s *Store) AllObservations(project, scope string, limit int) ([]Observation, error)

AllObservations returns recent observations ordered by most recent first (for TUI browsing).

func (*Store) AllSessions

func (s *Store) AllSessions(project string, limit int) ([]SessionSummary, error)

AllSessions returns recent sessions ordered by most recent first (for TUI browsing).

func (*Store) ApplyPulledMutation added in v1.8.0

func (s *Store) ApplyPulledMutation(targetKey string, mutation SyncMutation) error

func (*Store) Close

func (s *Store) Close() error

func (*Store) CreateSession

func (s *Store) CreateSession(id, project, directory string) error

func (*Store) DeleteObservation

func (s *Store) DeleteObservation(id int64, hardDelete bool) error

func (*Store) EndSession

func (s *Store) EndSession(id string, summary string) error

func (*Store) EnrollProject added in v1.8.0

func (s *Store) EnrollProject(project string) error

EnrollProject registers a project for cloud sync. Idempotent — re-enrolling an already-enrolled project is a no-op.

func (*Store) Export

func (s *Store) Export() (*ExportData, error)

func (*Store) FormatContext

func (s *Store) FormatContext(project, scope string) (string, error)

func (*Store) GetObservation

func (s *Store) GetObservation(id int64) (*Observation, error)

func (*Store) GetObservationBySyncID added in v1.8.0

func (s *Store) GetObservationBySyncID(syncID string) (*Observation, error)

func (*Store) GetSession

func (s *Store) GetSession(id string) (*Session, error)

func (*Store) GetSyncState added in v1.8.0

func (s *Store) GetSyncState(targetKey string) (*SyncState, error)

func (*Store) GetSyncedChunks

func (s *Store) GetSyncedChunks() (map[string]bool, error)

GetSyncedChunks returns a set of chunk IDs that have been imported/exported.

func (*Store) Import

func (s *Store) Import(data *ExportData) (*ImportResult, error)

func (*Store) IsProjectEnrolled added in v1.8.0

func (s *Store) IsProjectEnrolled(project string) (bool, error)

IsProjectEnrolled returns true if the given project is enrolled for cloud sync.

func (*Store) ListEnrolledProjects added in v1.8.0

func (s *Store) ListEnrolledProjects() ([]EnrolledProject, error)

ListEnrolledProjects returns all projects currently enrolled for cloud sync, ordered alphabetically by project name.

func (*Store) ListPendingSyncMutations added in v1.8.0

func (s *Store) ListPendingSyncMutations(targetKey string, limit int) ([]SyncMutation, error)

func (*Store) MarkSyncFailure added in v1.8.0

func (s *Store) MarkSyncFailure(targetKey, message string, backoffUntil time.Time) error

func (*Store) MarkSyncHealthy added in v1.8.0

func (s *Store) MarkSyncHealthy(targetKey string) error

func (*Store) PassiveCapture

func (s *Store) PassiveCapture(p PassiveCaptureParams) (*PassiveCaptureResult, error)

PassiveCapture extracts learnings from text and saves them as observations. It deduplicates against existing observations using content hash matching.

func (*Store) RecentObservations

func (s *Store) RecentObservations(project, scope string, limit int) ([]Observation, error)

func (*Store) RecentPrompts

func (s *Store) RecentPrompts(project string, limit int) ([]Prompt, error)

func (*Store) RecentSessions

func (s *Store) RecentSessions(project string, limit int) ([]SessionSummary, error)

func (*Store) RecordSyncedChunk

func (s *Store) RecordSyncedChunk(chunkID string) error

RecordSyncedChunk marks a chunk as imported/exported so it won't be processed again.

func (*Store) ReleaseSyncLease added in v1.8.0

func (s *Store) ReleaseSyncLease(targetKey, owner string) error

func (*Store) Search

func (s *Store) Search(query string, opts SearchOptions) ([]SearchResult, error)

func (*Store) SearchPrompts

func (s *Store) SearchPrompts(query string, project string, limit int) ([]Prompt, error)

func (*Store) SessionObservations

func (s *Store) SessionObservations(sessionID string, limit int) ([]Observation, error)

SessionObservations returns all observations for a specific session.

func (*Store) SkipAckNonEnrolledMutations added in v1.8.0

func (s *Store) SkipAckNonEnrolledMutations(targetKey string) (int64, error)

SkipAckNonEnrolledMutations acks (marks as skipped) all pending mutations that belong to non-enrolled projects, preventing journal bloat. Empty-project mutations are never skipped — they always sync regardless of enrollment.

func (*Store) Stats

func (s *Store) Stats() (*Stats, error)

func (*Store) Timeline

func (s *Store) Timeline(observationID int64, before, after int) (*TimelineResult, error)

func (*Store) UnenrollProject added in v1.8.0

func (s *Store) UnenrollProject(project string) error

UnenrollProject removes a project from cloud sync enrollment. Idempotent — unenrolling a non-enrolled project is a no-op.

func (*Store) UpdateObservation

func (s *Store) UpdateObservation(id int64, p UpdateObservationParams) (*Observation, error)

type SyncMutation added in v1.8.0

type SyncMutation struct {
	Seq        int64   `json:"seq"`
	TargetKey  string  `json:"target_key"`
	Entity     string  `json:"entity"`
	EntityKey  string  `json:"entity_key"`
	Op         string  `json:"op"`
	Payload    string  `json:"payload"`
	Source     string  `json:"source"`
	Project    string  `json:"project"`
	OccurredAt string  `json:"occurred_at"`
	AckedAt    *string `json:"acked_at,omitempty"`
}

type SyncState added in v1.8.0

type SyncState struct {
	TargetKey           string  `json:"target_key"`
	Lifecycle           string  `json:"lifecycle"`
	LastEnqueuedSeq     int64   `json:"last_enqueued_seq"`
	LastAckedSeq        int64   `json:"last_acked_seq"`
	LastPulledSeq       int64   `json:"last_pulled_seq"`
	ConsecutiveFailures int     `json:"consecutive_failures"`
	BackoffUntil        *string `json:"backoff_until,omitempty"`
	LeaseOwner          *string `json:"lease_owner,omitempty"`
	LeaseUntil          *string `json:"lease_until,omitempty"`
	LastError           *string `json:"last_error,omitempty"`
	UpdatedAt           string  `json:"updated_at"`
}

type TimelineEntry

type TimelineEntry struct {
	ID             int64   `json:"id"`
	SessionID      string  `json:"session_id"`
	Type           string  `json:"type"`
	Title          string  `json:"title"`
	Content        string  `json:"content"`
	ToolName       *string `json:"tool_name,omitempty"`
	Project        *string `json:"project,omitempty"`
	Scope          string  `json:"scope"`
	TopicKey       *string `json:"topic_key,omitempty"`
	RevisionCount  int     `json:"revision_count"`
	DuplicateCount int     `json:"duplicate_count"`
	LastSeenAt     *string `json:"last_seen_at,omitempty"`
	CreatedAt      string  `json:"created_at"`
	UpdatedAt      string  `json:"updated_at"`
	DeletedAt      *string `json:"deleted_at,omitempty"`
	IsFocus        bool    `json:"is_focus"` // true for the anchor observation
}

type TimelineResult

type TimelineResult struct {
	Focus        Observation     `json:"focus"`        // The anchor observation
	Before       []TimelineEntry `json:"before"`       // Observations before the focus (chronological)
	After        []TimelineEntry `json:"after"`        // Observations after the focus (chronological)
	SessionInfo  *Session        `json:"session_info"` // Session that contains the focus observation
	TotalInRange int             `json:"total_in_range"`
}

type UpdateObservationParams

type UpdateObservationParams struct {
	Type     *string `json:"type,omitempty"`
	Title    *string `json:"title,omitempty"`
	Content  *string `json:"content,omitempty"`
	Project  *string `json:"project,omitempty"`
	Scope    *string `json:"scope,omitempty"`
	TopicKey *string `json:"topic_key,omitempty"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL