longterm

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildTranscript

func BuildTranscript(messages []types.Message, maxChars int) string

BuildTranscript formats messages as a readable transcript, capped at maxChars by keeping the most recent content.

Types

type Entity

type Entity struct {
	ID           string    `json:"id"`
	UserID       string    `json:"user_id"`
	Name         string    `json:"name"`
	EntityType   string    `json:"entity_type"`
	Observations []string  `json:"observations"`
	CreatedAt    time.Time `json:"created_at"`
	UpdatedAt    time.Time `json:"updated_at"`
}

Entity is a named thing with a type and a list of observations. Modelled after the MCP memory server reference (servers/src/memory).

type EntityInput

type EntityInput struct {
	Name         string   `json:"name"`
	EntityType   string   `json:"entity_type"`
	Observations []string `json:"observations"`
}

EntityInput is used for upsert operations.

func ParseLLMResponse

func ParseLLMResponse(raw string) ([]EntityInput, error)

ParseLLMResponse extracts EntityInputs from a JSON string that may be wrapped in markdown fences or surrounded by explanatory prose.

type Extractor

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

Extractor runs LLM-powered extraction of entities and observations from session transcripts and persists them in the long-term memory graph.

Extraction is designed to be asynchronous and best-effort: any error is logged at DEBUG level and not surfaced to the user.

func NewExtractor

func NewExtractor(store Store, caller LLMCaller, cfg ExtractorConfig) *Extractor

NewExtractor creates an Extractor. Zero-value config fields are replaced with defaults.

func (*Extractor) Extract

func (e *Extractor) Extract(ctx context.Context, userID string, messages []types.Message) error

Extract analyses the conversation and upserts any extracted entities into the knowledge graph for userID.

It is safe to call from a goroutine: all errors are logged and the function always returns nil to the caller (extraction failures are non-fatal).

type ExtractorConfig

type ExtractorConfig struct {
	// MinTurns is the minimum number of user turns required before extraction
	// runs. Short sessions rarely contain facts worth persisting.
	// Default: 3.
	MinTurns int

	// MaxTranscriptChars caps the conversation snippet fed to the LLM.
	// Keeps extraction cheap; recent turns are preferred when truncating.
	// Default: 8000.
	MaxTranscriptChars int

	// Model is the LLM model used for extraction. Haiku-class recommended.
	// When Model.Model is empty the request is sent without an explicit model
	// field, relying on the caller's default.
	Model types.ModelIdentifier

	// ExtractionTimeout is the per-call deadline passed to CreateMessage.
	// Default: 45 s.
	ExtractionTimeout time.Duration
}

ExtractorConfig controls extraction behaviour.

func DefaultExtractorConfig

func DefaultExtractorConfig() ExtractorConfig

DefaultExtractorConfig returns sensible defaults.

type Graph

type Graph struct {
	Entities  []Entity   `json:"entities"`
	Relations []Relation `json:"relations"`
}

Graph is a result set containing entities and the relations that touch them.

type LLMCaller

type LLMCaller interface {
	CreateMessage(ctx context.Context, req types.APIRequest) (*types.APIResponse, error)
}

LLMCaller is the minimal interface for calling the provider API. *providers.Client satisfies this — defined here as an interface so the extractor can be tested without a live network call.

type ObservationInput

type ObservationInput struct {
	EntityName string   `json:"entity_name"`
	Contents   []string `json:"contents"`
}

ObservationInput appends observations to an existing entity.

type ObservationResult

type ObservationResult struct {
	EntityName        string   `json:"entity_name"`
	AddedObservations []string `json:"added_observations"`
}

ObservationResult reports what was actually added after deduplication.

type Relation

type Relation struct {
	ID           string    `json:"id"`
	UserID       string    `json:"user_id"`
	From         string    `json:"from"` // entity name
	To           string    `json:"to"`   // entity name
	RelationType string    `json:"relation_type"`
	CreatedAt    time.Time `json:"created_at"`
}

Relation is a directed edge between two entities (active-voice convention).

type RelationInput

type RelationInput struct {
	From         string `json:"from"`
	To           string `json:"to"`
	RelationType string `json:"relation_type"`
}

RelationInput is used for create operations.

type SQLiteStore

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

SQLiteStore implements Store using a SQLite database. Schema is initialized via migration 20260615_012_longterm_memory.

func NewSQLiteStore

func NewSQLiteStore(db *sql.DB) *SQLiteStore

NewSQLiteStore wraps an open *sql.DB as a longterm memory Store. The caller is responsible for closing the underlying DB.

func (*SQLiteStore) AddObservations

func (s *SQLiteStore) AddObservations(ctx context.Context, userID string, inputs []ObservationInput) ([]ObservationResult, error)

AddObservations appends new observations to existing entities. Duplicate observation strings (per entity) are silently skipped.

func (*SQLiteStore) OpenNodes

func (s *SQLiteStore) OpenNodes(ctx context.Context, userID string, names []string) (*Graph, error)

OpenNodes retrieves specific entities by exact name and their relations.

func (*SQLiteStore) RetrieveForContext

func (s *SQLiteStore) RetrieveForContext(ctx context.Context, userID, query string, maxTokens int) (string, error)

RetrieveForContext searches memory and formats results as a Markdown block.

func (*SQLiteStore) SearchNodes

func (s *SQLiteStore) SearchNodes(ctx context.Context, userID, query string) (*Graph, error)

SearchNodes performs case-insensitive substring search across entity names, types, and observation content.

func (*SQLiteStore) UpsertEntities

func (s *SQLiteStore) UpsertEntities(ctx context.Context, userID string, inputs []EntityInput) ([]Entity, error)

UpsertEntities creates entities that do not yet exist (deduplicates by name per user). Returns only the entities that were actually inserted.

type Store

type Store interface {
	// UpsertEntities creates entities that do not exist yet (deduplicates by name).
	// Returns only the entities that were actually inserted.
	UpsertEntities(ctx context.Context, userID string, inputs []EntityInput) ([]Entity, error)

	// AddObservations appends new observations to existing entities.
	// Duplicate observation strings are silently skipped.
	AddObservations(ctx context.Context, userID string, inputs []ObservationInput) ([]ObservationResult, error)

	// SearchNodes performs case-insensitive substring search across entity names,
	// entity types, and observation content. Returns matching entities plus all
	// relations where at least one endpoint is in the result set.
	SearchNodes(ctx context.Context, userID, query string) (*Graph, error)

	// OpenNodes returns specific entities by exact name and the relations that
	// touch them (at least one endpoint in the requested set).
	OpenNodes(ctx context.Context, userID string, names []string) (*Graph, error)

	// RetrieveForContext retrieves memory relevant to the current query and
	// formats it as a Markdown block capped to approximately maxTokens.
	// Returns an empty string when there is nothing relevant.
	RetrieveForContext(ctx context.Context, userID, query string, maxTokens int) (string, error)
}

Store is the persistence interface for the long-term memory knowledge graph. Concrete persistence implementations are injected by the embedding runtime. All operations are scoped to a single user via userID.

Jump to

Keyboard shortcuts

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