Documentation
¶
Overview ¶
Package memory defines the pluggable memory provider contract.
Every memory plugin implements Provider as its core interface. Optional capabilities are discovered via type assertion at runtime, following the same pattern as github.com/vaayne/anna/pkg/hooks.
Index ¶
- Constants
- func AgentIDFromContext(ctx context.Context) string
- func BuildPrompt(text string, opts SummarizeOptions) string
- func BuildTool(provider Provider, opts ...ToolOption) tools.Tool
- func EstimateTokens(text string) int
- func MessageRole(msg ai.Message) string
- func MessageText(msg ai.Message) string
- func MessageTimestamp(msg ai.Message) time.Time
- func SessionIDFromContext(ctx context.Context) string
- func UserIDFromContext(ctx context.Context) int64
- func WithAgentID(ctx context.Context, agentID string) context.Context
- func WithChangeSource(ctx context.Context, source ChangeSource) context.Context
- func WithSessionID(ctx context.Context, sessionID string) context.Context
- func WithUserID(ctx context.Context, userID int64) context.Context
- type ChangeEntry
- type ChangeSource
- type ChangelogReader
- type ChangelogWriter
- type CompactionMode
- type CompactionResult
- type Compactor
- type ConstraintEntry
- type ConstraintStore
- type DescribeResult
- type ExpandChild
- type ExpandMessage
- type ExpandResult
- type Explorer
- type LLMSummarizer
- type ListOptions
- type ProfileStore
- type Provider
- type Reviewer
- type SearchQuery
- type SearchResult
- type SearchScope
- type Searcher
- type Session
- type SessionInfo
- type SessionManager
- type SessionSnapshot
- type SessionSnapshotStore
- type SessionStats
- type StaticSummarizer
- type SummarizeOptions
- type Summarizer
- type ToolOption
- type VersionedConstraintStore
- type VersionedProfileStore
Constants ¶
const ( SummarizePolicyNormal = "normal" SummarizePolicyAggressive = "aggressive" )
SummarizePolicy constants control how aggressively content is compressed.
Variables ¶
This section is empty.
Functions ¶
func AgentIDFromContext ¶
AgentIDFromContext extracts the agent ID from context.
func BuildPrompt ¶
func BuildPrompt(text string, opts SummarizeOptions) string
BuildPrompt constructs the appropriate summarization prompt.
func BuildTool ¶
func BuildTool(provider Provider, opts ...ToolOption) tools.Tool
BuildTool inspects provider capabilities and returns a memory tool whose available actions match exactly what the provider supports. If the provider supports no optional capabilities, the tool still exists but only offers a "status" action.
func EstimateTokens ¶
EstimateTokens returns a rough token count (~4 chars per token).
func MessageRole ¶
MessageRole returns the role string for an ai.Message.
func MessageText ¶
MessageText extracts the plain text content from an ai.Message. Returns the text for user/assistant messages, or the tool result for tool messages.
func MessageTimestamp ¶
MessageTimestamp returns the timestamp of an ai.Message.
func SessionIDFromContext ¶
SessionIDFromContext extracts the session ID from context.
func UserIDFromContext ¶
UserIDFromContext extracts the user ID from context.
func WithAgentID ¶
WithAgentID attaches an agent ID to the context.
func WithChangeSource ¶ added in v0.18.0
func WithChangeSource(ctx context.Context, source ChangeSource) context.Context
WithChangeSource stores a ChangeSource in the context. This lets callers (e.g. Reflect) tag writes without changing function signatures.
func WithSessionID ¶
WithSessionID attaches a session ID to the context.
Types ¶
type ChangeEntry ¶ added in v0.18.0
type ChangeEntry struct {
ID int64
UserID int64
AgentID string
SessionID string
Scope string // "profile", "soul", "constraint", "skill", "compaction"
Action string // "create", "update", "delete", "compact"
Source ChangeSource
MemoryVersionBefore *int64
MemoryVersionAfter *int64
BeforeText string
AfterText string
CreatedAt string
}
ChangeEntry represents one changelog record.
type ChangeSource ¶ added in v0.18.0
type ChangeSource string
ChangeSource identifies who triggered a memory write.
const ( SourceUser ChangeSource = "user" SourceAgent ChangeSource = "agent" SourceReflect ChangeSource = "reflect" SourceSystem ChangeSource = "system" )
func ChangeSourceFromContext ¶ added in v0.18.0
func ChangeSourceFromContext(ctx context.Context) ChangeSource
ChangeSourceFromContext retrieves the ChangeSource from context. Returns SourceAgent if not set.
type ChangelogReader ¶ added in v0.18.0
type ChangelogReader interface {
// ReadChangelog returns the last N changelog entries for a given scope.
ReadChangelog(ctx context.Context, userID int64, agentID string, scope string, limit int) ([]ChangeEntry, error)
}
ChangelogReader is implemented by providers that expose memory write history.
type ChangelogWriter ¶ added in v0.18.0
type ChangelogWriter interface {
// WriteChangelog records a memory change.
WriteChangelog(ctx context.Context, entry ChangeEntry) error
}
ChangelogWriter is implemented by providers that record memory write history.
type CompactionMode ¶
type CompactionMode int
CompactionMode controls compaction behavior.
const ( // CompactionIncremental runs one leaf pass + one condensed pass. CompactionIncremental CompactionMode = iota // CompactionFull repeats until no more compaction is possible. CompactionFull )
func (CompactionMode) String ¶
func (m CompactionMode) String() string
String returns the human-readable name of the compaction mode.
type CompactionResult ¶
type CompactionResult struct {
LeafSummariesCreated int
CondensedSummariesCreated int
MessagesCompacted int
TokensBefore int
TokensAfter int
Duration time.Duration
}
CompactionResult reports what a compaction cycle accomplished.
type Compactor ¶
type Compactor interface {
// NeedsCompaction returns true if the session's context has grown large enough
// to warrant compaction. threshold is a fraction of the session's token budget
// (e.g. 0.75 means "compact when context is 75% full").
NeedsCompaction(ctx context.Context, session Session, threshold float64) bool
// Compact runs the compaction algorithm on the session.
// Incremental mode runs a single summarisation pass (fast, called automatically).
// Full mode runs repeated passes until no further reduction is possible
// (slow, called on demand e.g. via /compact slash command).
Compact(ctx context.Context, session Session, mode CompactionMode) (*CompactionResult, error)
}
Compactor is implemented by providers that support background compaction. The Pool calls NeedsCompaction before each chat turn and Compact when needed.
type ConstraintEntry ¶ added in v0.18.0
type ConstraintEntry struct {
ID string `json:"id"`
Text string `json:"text"`
CreatedAt string `json:"created_at"`
}
ConstraintEntry represents a single user constraint.
type ConstraintStore ¶ added in v0.18.0
type ConstraintStore interface {
// GetConstraints returns all active constraints for the (userID, agentID) pair.
GetConstraints(ctx context.Context, userID int64, agentID string) ([]ConstraintEntry, error)
// AddConstraint adds a new constraint with a generated UUID-like ID.
// Returns the updated list of constraints.
AddConstraint(ctx context.Context, userID int64, agentID string, text string) ([]ConstraintEntry, error)
// RemoveConstraint removes the constraint with the given ID.
// Returns the updated list of constraints.
RemoveConstraint(ctx context.Context, userID int64, agentID string, id string) ([]ConstraintEntry, error)
}
ConstraintStore is implemented by providers that support storing user-defined hard constraints (rules the agent must always follow). Constraints are separate from Profile to give them special protection: Reflect cannot modify them; only user-initiated writes are allowed by convention.
type DescribeResult ¶
type DescribeResult struct {
SummaryID string
Kind string // "leaf" or "condensed"
Depth int // 0 = leaf, 1+ = condensed
Content string // the summary text
EarliestAt *time.Time // timestamp of oldest source message
LatestAt *time.Time // timestamp of newest source message
DescendantCount int // total original messages this summary covers
ParentIDs []string // summaries that contain this one (condensed parents)
ChildIDs []string // summaries or messages this one was built from
}
DescribeResult represents summary metadata and lineage.
type ExpandChild ¶
ExpandChild is a child summary in an expand result.
type ExpandMessage ¶
ExpandMessage is a source message in an expand result.
type ExpandResult ¶
type ExpandResult struct {
SummaryID string
// For leaf summaries: the original source messages.
Messages []ExpandMessage
// For condensed summaries: the child summaries.
Children []ExpandChild
}
ExpandResult represents drill-down results from exploring a summary.
type Explorer ¶
type Explorer interface {
// Describe returns metadata and lineage for a summary ID.
Describe(ctx context.Context, summaryID string) (*DescribeResult, error)
// Expand drills into a summary:
// - For leaf summaries: returns the original source messages
// - For condensed summaries: returns the child summaries
// tokenCap limits how many tokens of content are returned.
Expand(ctx context.Context, summaryID string, tokenCap int) (*ExpandResult, error)
}
Explorer is implemented by providers that store summaries in a navigable hierarchy. It lets the agent inspect and drill into compressed history.
Note: these methods take summaryID only, not Session. Summary IDs are globally unique (e.g. "sum_a1b2c3d4") and already scoped to a conversation internally.
type LLMSummarizer ¶
type LLMSummarizer struct {
// Generate calls the LLM with the given prompt and returns the response text.
Generate func(ctx context.Context, prompt string) (string, error)
}
LLMSummarizer generates summaries using an LLM via a callback function.
func (*LLMSummarizer) Summarize ¶
func (s *LLMSummarizer) Summarize(ctx context.Context, text string, opts SummarizeOptions) (string, error)
Summarize generates a summary with escalation: normal -> aggressive -> deterministic fallback.
type ListOptions ¶
type ListOptions struct {
AgentID string // filter by agent (empty = all)
UserID int64 // filter by user (0 = all)
IncludeArchived bool
Limit int // 0 = no limit
Offset int // skip first N matching results
}
ListOptions controls session listing filters.
type ProfileStore ¶
type ProfileStore interface {
// GetProfile returns the current user profile for the (userID, agentID) pair.
// Returns ("", nil) if no profile exists yet (not an error).
GetProfile(ctx context.Context, userID int64, agentID string) (string, error)
// SetProfile overwrites the user profile for the (userID, agentID) pair.
// Callers are responsible for merging new content with existing content
// before calling SetProfile — this method always replaces, never appends.
SetProfile(ctx context.Context, userID int64, agentID string, content string) error
// GetAgentSoul returns the agent soul for the (userID, agentID) pair.
// The soul defines the agent's identity, personality, and behavior as
// customised by this specific user. Returns ("", nil) if not set.
GetAgentSoul(ctx context.Context, userID int64, agentID string) (string, error)
// SetAgentSoul overwrites the agent soul for the (userID, agentID) pair.
// Callers are responsible for merging; this method always replaces.
SetAgentSoul(ctx context.Context, userID int64, agentID string, content string) error
}
ProfileStore is implemented by providers that support per-user-per-agent persistent memory: agent soul (identity/personality customization) and user profile (facts/context about the user).
Both are scoped to (userID, agentID) — each user can customise the agent's soul independently, and the agent maintains separate profile notes per user. Content is free-form text managed entirely by the agent. The system injects both into the system prompt at session start.
type Provider ¶
type Provider interface {
// Name returns the plugin identifier (e.g. "lcm", "simple").
// Used in logs and admin UI.
Name() string
// Bootstrap ensures the session is initialized and ready for use.
// Called once at the start of every Pool.Chat call before any Append or Assemble.
// Implementations use this to create conversation records, initialize caches,
// or establish remote connections for the session.
Bootstrap(ctx context.Context, session Session) error
// Append persists one or more messages to the session's event log.
// Messages must be appended in the order they arrive.
// Callers pass all messages from a single turn together so implementations
// can store them in a single atomic transaction if they choose.
//
// Concurrency: implementations MUST be safe for concurrent Append calls
// on different sessions. Concurrent Append calls on the SAME session
// MUST be serialised by the implementation (see Concurrency Contract).
Append(ctx context.Context, session Session, msgs ...ai.Message) error
// Assemble builds the context window to send to the LLM.
// budget: maximum number of tokens the returned messages may consume.
// freshTail: minimum number of recent messages to always include verbatim,
// regardless of budget pressure. Implementations MUST honour this.
// Returns messages in chronological order (oldest first).
// Older content that does not fit in the budget is either summarised
// (if the plugin supports Compactor) or omitted.
Assemble(ctx context.Context, session Session, budget, freshTail int) ([]ai.Message, error)
// Stats returns basic statistics about a session's memory state.
// Used by the memory tool's "status" action and by admin endpoints.
// Returns zero-value stats (not an error) if the session does not exist.
Stats(ctx context.Context, session Session) (SessionStats, error)
// Close releases any resources held by the provider (DB connections, caches, etc.).
// Called when the Pool shuts down. Must be safe to call multiple times.
Close() error
}
Provider is the memory plugin contract. Every memory plugin must implement this interface. Optional capabilities are discovered via type assertion — see Capability Interfaces.
func Unwrap ¶
Unwrap returns the innermost Provider by recursively unwrapping traced layers. If p does not implement the unwrapper interface, p itself is returned.
func WithTracing ¶
WithTracing wraps a Provider to emit PostMemoryCall hooks after each operation. hooksFn is called on each operation to get the current HookSet; it may return nil. The returned Provider implements all optional capability interfaces (Compactor, Searcher, Explorer, ProfileStore, SessionManager, Reviewer). Methods for capabilities not supported by the inner provider return sensible zero values or errors. Use Unwrap to check the inner provider's actual capabilities.
The Detail field is always populated with content previews. The trace hook decides whether to emit it based on log level (see [LevelTrace]).
type Reviewer ¶
type Reviewer interface {
// BuildReviewContext returns a text representation of the conversation
// suitable for passing to a reviewer agent's prompt.
//
// since: if non-zero, only include content created after this time.
// The provider should include prior context (e.g. summaries from before
// this timestamp) to give the reviewer enough background.
// If zero, include all content.
//
// Returns ("", nil) if there is no content to review.
BuildReviewContext(ctx context.Context, session Session, since time.Time) (string, error)
}
Reviewer is implemented by providers that can format conversation content for review by a background agent (the reflect system).
This is deliberately a single method. Watermark tracking (which sessions have been reviewed, when) is not the memory plugin's concern — it belongs to the consumer (`plugins/reflect`). The memory plugin's only job is: "given a session and an optional time boundary, produce reviewable text."
type SearchQuery ¶
type SearchQuery struct {
Text string // search term (keyword or natural language depending on plugin)
Scope SearchScope // which layer of storage to search
Limit int // max results (default 20)
}
SearchQuery describes a search request.
type SearchResult ¶
type SearchResult struct {
SourceType string // "message" or "summary"
SourceID string // message ID or summary ID
Content string // snippet of the matching content (truncated at ~500 chars)
Score float64 // relevance score: 0 for keyword match, 0.0-1.0 for semantic
Timestamp time.Time // when the source was created
}
SearchResult represents a single search hit.
type SearchScope ¶
type SearchScope int
SearchScope controls which storage layer to search.
const ( SearchScopeBoth SearchScope = iota // default: search everything SearchScopeMessages // raw messages only SearchScopeSummaries // summaries only )
type Searcher ¶
type Searcher interface {
Search(ctx context.Context, session Session, query SearchQuery) ([]SearchResult, error)
}
Searcher is implemented by providers that support history search.
type Session ¶
type Session struct {
ID string // unique session key (e.g. "default:cli:42:main")
AgentID string // agent this session belongs to (e.g. "default")
UserID int64 // internal user ID (0 for anonymous/legacy)
Channel string // originating channel (e.g. "cli", "telegram")
}
Session identifies the context of a single conversation. It is created by Pool.Chat and passed to all Provider methods.
type SessionInfo ¶
type SessionInfo struct {
ID string
AgentID string
UserID int64
Channel string
Title string // auto-generated from first message
CreatedAt time.Time
LastActive time.Time
Archived bool
}
SessionInfo holds metadata about a session.
type SessionManager ¶
type SessionManager interface {
// SaveInfo persists or updates session metadata.
SaveInfo(ctx context.Context, info SessionInfo) error
// LoadInfo retrieves metadata for a single session.
LoadInfo(ctx context.Context, sessionID string) (SessionInfo, error)
// ListInfo lists sessions matching the options.
ListInfo(ctx context.Context, opts ListOptions) ([]SessionInfo, error)
// LoadHistory returns the complete raw message history for a session
// in chronological order. Used by the admin panel viewer and export.
LoadHistory(ctx context.Context, sessionID string) ([]ai.Message, error)
}
SessionManager is implemented by providers that support session lifecycle management.
type SessionSnapshot ¶ added in v0.18.0
type SessionSnapshot struct {
SessionID string
UserID int64
AgentID string
Version int64
// UpdatedAt is the wall-clock time when this snapshot was last advanced.
// Used to filter knowledge entries so that knowledge activated after the
// snapshot was taken does not appear in the frozen session.
UpdatedAt time.Time
}
SessionSnapshot holds the frozen version for a session.
type SessionSnapshotStore ¶ added in v0.18.0
type SessionSnapshotStore interface {
// GetOrCreateSessionSnapshot returns the snapshot for the session, creating it
// if it doesn't exist. When creating, freezes the current ctx_agent_memory.version.
GetOrCreateSessionSnapshot(ctx context.Context, sessionID string, userID int64, agentID string) (SessionSnapshot, error)
// AdvanceSessionSnapshot updates the snapshot version to the current
// ctx_agent_memory.version for (userID, agentID).
// Called after front-end memory writes so the current session sees the update.
AdvanceSessionSnapshot(ctx context.Context, sessionID string, userID int64, agentID string) error
}
SessionSnapshotStore is implemented by providers that support session snapshots.
type SessionStats ¶
type SessionStats struct {
MessageCount int // total messages stored for this session
TokenCount int // estimated total tokens across all stored messages
SummaryCount int // number of summaries (0 for providers without Compactor)
OldestAt time.Time // timestamp of the earliest message (zero if empty)
NewestAt time.Time // timestamp of the most recent message (zero if empty)
}
SessionStats contains basic statistics about a session's memory state. Every provider can produce this since it only requires knowledge of what was stored via Append.
type StaticSummarizer ¶
StaticSummarizer always returns a fixed response (for testing).
func (*StaticSummarizer) Summarize ¶
func (s *StaticSummarizer) Summarize(_ context.Context, _ string, _ SummarizeOptions) (string, error)
Summarize returns the static response.
type SummarizeOptions ¶
type SummarizeOptions struct {
IsCondensed bool
Depth int
Aggressive bool
Previous string // previous summary for continuity
TargetTokens int
}
SummarizeOptions controls summarization behavior.
type Summarizer ¶
type Summarizer interface {
Summarize(ctx context.Context, text string, opts SummarizeOptions) (string, error)
}
Summarizer generates summaries from content.
type ToolOption ¶
type ToolOption func(*toolConfig)
ToolOption configures the generated memory tool.
func WithActionsOnly ¶
func WithActionsOnly(actions ...string) ToolOption
WithActionsOnly restricts the tool to the named actions only. Actions not in the list are omitted even if the provider supports them.
func WithReadOnlyProfile ¶
func WithReadOnlyProfile() ToolOption
WithReadOnlyProfile disables the profile_update action. Used when building the tool for the self-improve reviewer agent, which should read but not arbitrarily overwrite profile notes.
func WithReadOnlySoul ¶
func WithReadOnlySoul() ToolOption
WithReadOnlySoul disables the soul_update action.
type VersionedConstraintStore ¶ added in v0.18.0
type VersionedConstraintStore interface {
GetConstraintsAt(ctx context.Context, userID int64, agentID string, version int64) ([]ConstraintEntry, error)
}
VersionedConstraintStore is implemented by providers that can read constraints at a specific memory version.
type VersionedProfileStore ¶ added in v0.18.0
type VersionedProfileStore interface {
GetProfileAt(ctx context.Context, userID int64, agentID string, version int64) (string, error)
GetAgentSoulAt(ctx context.Context, userID int64, agentID string, version int64) (string, error)
}
VersionedProfileStore is implemented by providers that can read profile/soul at a specific memory version (from the changelog). Version 0 or negative means "current" (same as ProfileStore).
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package memorytest provides test doubles and conformance testing for memory.Provider implementations.
|
Package memorytest provides test doubles and conformance testing for memory.Provider implementations. |