Documentation
¶
Index ¶
- Constants
- Variables
- func DefaultDBPath() string
- func LightweightTreeAsText(tree map[string]TopicTree, topFacts []Node) string
- func LightweightTreeAsTextWithHighlight(tree map[string]TopicTree, topFacts []Node, relevantKeys map[string]float32) string
- func LightweightTreeAsTextWithLimit(tree map[string]TopicTree, topFacts []Node, maxSummaryChars int) string
- type ChatClient
- type CollectionStats
- type ConceptTree
- type Document
- type Edge
- type EmbedClient
- type Graph
- func (g *Graph) AddFact(ctx context.Context, opts GraphOptions) (*Node, error)
- func (g *Graph) BuildLightweightTree(ctx context.Context, sessionID string, f NodeFilter, queryVec []float32, ...) (map[string]TopicTree, []Node, error)
- func (g *Graph) BuildTree(ctx context.Context, sessionID string) (map[string]TopicTree, error)
- func (g *Graph) BuildTreeFiltered(ctx context.Context, sessionID string, f NodeFilter) (map[string]TopicTree, error)
- func (g *Graph) ProjectRecall(ctx context.Context, opts ProjectRecallOptions) (*ProjectRecallResult, error)
- func (g *Graph) Recall(ctx context.Context, opts RecallOptions) (*RecallResult, error)
- type GraphOptions
- type GraphOpts
- type Memory
- func (m *Memory) CreateCollection(ctx context.Context, name string) (int64, error)
- func (m *Memory) DeleteCollection(ctx context.Context, name string) error
- func (m *Memory) Enabled() bool
- func (m *Memory) ReadMemory(ctx context.Context, sessionID string) string
- func (m *Memory) RecallMemory(ctx context.Context, sessionID, question string, chat ChatClient) string
- func (m *Memory) RecallProjectMemory(ctx context.Context, req ProjectRecallRequest) string
- func (m *Memory) RefreshAll(ctx context.Context) error
- func (m *Memory) SemanticSearch(ctx context.Context, collection, query string, topK int) ([]SearchResult, error)
- func (m *Memory) Stats(ctx context.Context) (col, doc, nodes, edges int, err error)
- func (m *Memory) UpsertDocument(ctx context.Context, collection, content string) (int64, error)
- func (m *Memory) WriteMemory(ctx context.Context, scope Scope, question, response string, chat ChatClient)
- type Node
- type NodeFilter
- type NodeType
- type Placement
- type ProjectFilter
- type ProjectRecallOptions
- type ProjectRecallRequest
- type ProjectRecallResult
- type RecallOptions
- type RecallResult
- type RelatedConcept
- type Scope
- type SearchResult
- type SessionMeta
- type SessionUpsert
- type Store
- func (s *Store) AddEdge(e Edge) error
- func (s *Store) AddNode(n Node) (*Node, error)
- func (s *Store) BackfillProject(projectID string, sessionTypes map[string]string) (int64, error)
- func (s *Store) Close() error
- func (s *Store) DB() *sql.DB
- func (s *Store) DeleteEdge(sessionID, fromKey, toKey string) error
- func (s *Store) DeleteNode(sessionID, key string) error
- func (s *Store) DeleteSession(sessionID string) error
- func (s *Store) Embeddings(sessionID string) (map[string][]float32, error)
- func (s *Store) EnsureSession(sessionID string) error
- func (s *Store) EnsureSessionMeta(u SessionUpsert) error
- func (s *Store) GetFirstFact(sessionID string) (*Node, error)
- func (s *Store) GetLastFact(sessionID string) (*Node, error)
- func (s *Store) GetNode(sessionID, key string) (*Node, error)
- func (s *Store) GetNodeAt(sessionID string, order int) (*Node, error)
- func (s *Store) ListEdges(sessionID string) ([]Edge, error)
- func (s *Store) ListNodes(sessionID string, filterType NodeType) ([]Node, error)
- func (s *Store) ListNodesFiltered(sessionID string, f NodeFilter) ([]Node, error)
- func (s *Store) ListProjectConcepts(projectID string, f ProjectFilter, limit int) ([]Node, error)
- func (s *Store) ListProjectTopics(projectID string, f ProjectFilter, limit int) ([]TopicCount, error)
- func (s *Store) ListSessions() ([]SessionMeta, error)
- func (s *Store) ProjectFactsAt(projectID, sessionID string, orders []int, f ProjectFilter) ([]Node, error)
- func (s *Store) ProjectSessionNames(projectID string) (map[string]string, error)
- func (s *Store) ProjectStats(projectID string) (sessions, topics, facts int, err error)
- func (s *Store) ScanProjectFacts(projectID string, f ProjectFilter, fn func(Node, []float32)) error
- func (s *Store) SetEmbedding(sessionID, key string, emb []float32) error
- func (s *Store) Stats(sessionID string) (topics, concepts, facts int, err error)
- func (s *Store) UpdateNodeEnrichment(sessionID, key, summary string, labels []string) error
- type TopicCount
- type TopicTree
Constants ¶
const DocumentDefaultCollection = "default"
DocumentDefaultCollection is the fallback collection name.
Variables ¶
var DefaultProjectSessionTypes = []string{"build", "plan"}
DefaultProjectSessionTypes are the session types project-scoped recall reads. Subagent, note, index and search sessions also write memory, but their turns are tool traces rather than conversations with the user — including them drowns project recall in noise.
Functions ¶
func DefaultDBPath ¶ added in v0.2.1
func DefaultDBPath() string
DefaultDBPath returns the default path for the memory database.
func LightweightTreeAsText ¶ added in v0.2.1
func LightweightTreeAsTextWithHighlight ¶ added in v0.2.1
Types ¶
type ChatClient ¶ added in v0.2.1
ChatClient is the minimal interface the Graph needs to call an LLM. It wraps a blocking chat call — callers can adapt streaming providers.
func NewChatClient ¶ added in v0.2.1
func NewChatClient(p provider.Provider, model string) ChatClient
NewChatClient creates a blocking ChatClient from an ogcode Provider. model is the specific model ID to use; if empty the provider's default (Models()[0]) is used.
type CollectionStats ¶ added in v0.2.1
type CollectionStats struct {
Collections int `json:"collections"`
Documents int `json:"documents"`
Nodes int `json:"nodes"`
Edges int `json:"edges"`
}
CollectionStats is returned by Stats.
type ConceptTree ¶ added in v0.2.1
type ConceptTree struct {
Name string `json:"name"`
Facts []Node `json:"facts"`
RelatedConcepts []string `json:"related,omitempty"`
}
ConceptTree is the readable tree for one concept.
type Document ¶ added in v0.2.1
type Document struct {
ID int64 `json:"id"`
Collection string `json:"collection"`
Content string `json:"content"`
CreatedAt int64 `json:"createdAt"`
}
Document is an unstructured text fragment tied to a collection.
type Edge ¶ added in v0.2.1
type Edge struct {
ID int64 `json:"id"`
SessionID string `json:"sessionId"`
FromKey string `json:"fromKey"` // concept key
ToKey string `json:"toKey"` // concept key (cross-topic allowed)
RelType string `json:"relType"` // e.g. "related", "prerequisite", "opposite"
Weight float32 `json:"weight"`
CreatedAt int64 `json:"createdAt"`
}
Edge represents a named relationship between two nodes.
type EmbedClient ¶ added in v0.2.1
EmbedClient returns embedding vectors for input strings.
func NewEmbedClient ¶ added in v0.2.1
func NewEmbedClient(e provider.Embedder) EmbedClient
NewEmbedClient creates an EmbedClient from an ogcode Embedder.
type Graph ¶ added in v0.2.1
type Graph struct {
Store *Store
Embed EmbedClient
}
Graph orchestrates the knowledge graph lifecycle.
Embed is the inbuilt local embedder (always present when memory is enabled). The synthesis LLM is NOT stored here — it is supplied per call via GraphOptions.Chat / RecallOptions.Chat so memory uses the session's currently selected model rather than a server-wide default.
func (*Graph) AddFact ¶ added in v0.2.1
AddFact stores a new fact and reorganizes the graph. Embedding is required.
func (*Graph) BuildLightweightTree ¶ added in v0.2.1
func (g *Graph) BuildLightweightTree(ctx context.Context, sessionID string, f NodeFilter, queryVec []float32, limit int) (map[string]TopicTree, []Node, error)
BuildLightweightTree builds a lightweight tree ready for LLM consumption.
func (*Graph) BuildTree ¶ added in v0.2.1
BuildTree constructs the hierarchical memory tree for a session.
func (*Graph) BuildTreeFiltered ¶ added in v0.2.1
func (g *Graph) BuildTreeFiltered(ctx context.Context, sessionID string, f NodeFilter) (map[string]TopicTree, error)
BuildTreeFiltered constructs the tree filtered by given bounds.
func (*Graph) ProjectRecall ¶ added in v0.23.0
func (g *Graph) ProjectRecall(ctx context.Context, opts ProjectRecallOptions) (*ProjectRecallResult, error)
ProjectRecall runs semantic recall across every session in a project.
func (*Graph) Recall ¶ added in v0.2.1
func (g *Graph) Recall(ctx context.Context, opts RecallOptions) (*RecallResult, error)
type GraphOptions ¶ added in v0.2.1
type GraphOptions struct {
SessionID string
// ProjectID, SessionType and SessionName describe the session's workspace.
// They are denormalized onto every node written so project-scoped recall can
// filter and attribute facts without reaching into the session database.
ProjectID string
SessionType string
SessionName string
Question string
Response string
UserTopic string
// Chat is the synthesis LLM client used for topic/concept inference and
// enrichment on this call. It should be built from the session's selected
// provider+model. When nil, placement and enrichment fall back to
// heuristics (no LLM call).
Chat ChatClient
}
GraphOptions tunes Graph inference behavior.
type GraphOpts ¶ added in v0.2.1
type GraphOpts struct {
// EmbedProvider is the provider used for text embeddings. Must satisfy
// provider.Embedder. In practice this is always the inbuilt LocalEmbedder.
EmbedProvider provider.Provider
}
GraphOpts holds dependencies for initializing agentic memory.
Embedding is always produced by the inbuilt local embedder (gte-small) — there is no embedder configuration. The synthesis LLM (topic/concept inference and recall) is NOT configured here: it is supplied per request by the caller, using the same provider+model the user selected for their session. See WriteMemory and RecallWith.
type Memory ¶
Memory provides the agentic memory lifecycle: read, recall, and write. It wraps a local SQLite-backed knowledge graph with optional LLM inference.
func New ¶
New creates a Memory backed by local SQLite graph store. The synthesis LLM is not wired here — it is injected per call via WriteMemory/RecallWith so that memory uses the session's currently selected model.
func (*Memory) CreateCollection ¶ added in v0.2.1
CreateCollection inserts a new collection.
func (*Memory) DeleteCollection ¶ added in v0.2.1
DeleteCollection removes a collection including its documents.
func (*Memory) ReadMemory ¶
ReadMemory fetches the full session knowledge graph as text.
func (*Memory) RecallMemory ¶
func (m *Memory) RecallMemory(ctx context.Context, sessionID, question string, chat ChatClient) string
RecallMemory performs semantic recall for a specific question. chat is the synthesis LLM client built from the session's selected provider+model; when nil, recall returns the raw semantically filtered tree without synthesis.
func (*Memory) RecallProjectMemory ¶ added in v0.23.0
func (m *Memory) RecallProjectMemory(ctx context.Context, req ProjectRecallRequest) string
RecallProjectMemory performs semantic recall across every conversation held in a project. chat is the synthesis LLM built from the session's selected model; when nil, the assembled cross-session context is returned without synthesis.
func (*Memory) RefreshAll ¶ added in v0.2.1
RefreshAll recomputes all embeddings — both collection documents and graph facts — so it is the recovery path after switching embedding provider. Without re-embedding the graph nodes, session and project recall keep scoring against stale old-dimensionality vectors and (with the cosine dimension guard) silently match nothing.
func (*Memory) SemanticSearch ¶ added in v0.2.1
func (m *Memory) SemanticSearch(ctx context.Context, collection, query string, topK int) ([]SearchResult, error)
SemanticSearch runs a vector search across a collection.
func (*Memory) Stats ¶ added in v0.2.1
Stats returns total counts across all collections and graph tables.
func (*Memory) UpsertDocument ¶ added in v0.2.1
UpsertDocument stores or updates a document and computes its embedding using the currently configured embedder.
func (*Memory) WriteMemory ¶
func (m *Memory) WriteMemory(ctx context.Context, scope Scope, question, response string, chat ChatClient)
WriteMemory persists a conversation turn. chat is the synthesis LLM client to use for topic/concept inference and enrichment — it should be built from the same provider+model the user selected for the current session. When chat is nil, the fact is stored without LLM topic inference (placement falls back to heuristic). Synthesis runs in a background goroutine; the chat client is captured at dispatch time so it reflects the session's model even though the call is asynchronous.
type Node ¶ added in v0.2.1
type Node struct {
ID int64 `json:"id"`
SessionID string `json:"sessionId"`
ProjectID string `json:"projectId,omitempty"`
SessionType string `json:"sessionType,omitempty"`
Type NodeType `json:"type"`
Key string `json:"key"`
Content string `json:"content,omitempty"` // question + " [ANSWER] " + response for facts
Question string `json:"question,omitempty"` // original question
Response string `json:"response,omitempty"` // original answer
TopicName string `json:"topicName,omitempty"` // only set for concept/fact nodes
Summary string `json:"summary,omitempty"` // LLM-generated one-line summary per fact
Labels []string `json:"labels,omitempty"` // LLM-generated labels per fact
Order int `json:"order,omitempty"` // position in conversation (1-indexed)
CreatedAt int64 `json:"createdAt"`
AccessedAt int64 `json:"accessedAt"`
}
Node is the fundamental unit in the knowledge graph.
ProjectID and SessionType are denormalized copies of the owning session's project directory and type. They are stamped at write time so project-scoped recall can filter without joining against the per-project session database (which lives in a different file and, for worktree sessions, keys sessions by a directory the memory store never sees).
type NodeFilter ¶ added in v0.2.1
type NodeFilter struct {
Type NodeType
Since int64 // unix milliseconds; 0 = no lower bound
Until int64 // unix milliseconds; 0 = no upper bound
FromOrder int // 1-indexed inclusive; 0 = no lower bound
ToOrder int // 1-indexed inclusive; 0 = no upper bound
TopicName string // empty = any topic
}
NodeFilter captures all optional bounds on a node query.
type NodeType ¶ added in v0.2.1
type NodeType string
NodeType distinguishes the three levels in the hierarchy.
type ProjectFilter ¶ added in v0.23.0
type ProjectFilter struct {
Since int64 // unix milliseconds; 0 = no lower bound
Until int64 // unix milliseconds; 0 = no upper bound
SessionTypes []string // empty = any session type
TopicName string // empty = any topic
ExcludeSession string // session ID to skip (usually the caller's own)
// OnlySession restricts the query to a single conversation. It is how the
// project pipeline — dated, attributed, recency-ranked — gets pointed at just
// the current session. It takes precedence over SessionTypes: the caller
// named the session explicitly, so its type is not a reason to skip it.
OnlySession string
}
ProjectFilter bounds a project-scoped query. Session-scoped NodeFilter cannot be reused because project queries span many sessions, where the per-session "order" column is not comparable across rows.
type ProjectRecallOptions ¶ added in v0.23.0
type ProjectRecallOptions struct {
ProjectID string
Question string
Limit int // max semantically matched facts fed to synthesis
PerSessionCap int // max matched facts contributed by any one session
MaxRounds int // max refinement rounds
Threshold float32 // confidence threshold to stop early
HalfLifeDays float64 // recency half-life for the score boost
MaxChars int // char budget for the facts block
Since int64 // unix ms; 0 = no lower bound
Until int64 // unix ms; 0 = no upper bound
SessionTypes []string // empty = every session type
ExcludeSession string // session to skip, usually the caller's own
OnlySession string // restrict to one conversation; overrides SessionTypes
TopicName string // restrict to one topic
// Chat is the synthesis LLM, built from the session's selected model. When
// nil, recall returns the assembled context without synthesis.
Chat ChatClient
}
ProjectRecallOptions tunes a project-scoped recall.
type ProjectRecallRequest ¶ added in v0.23.0
type ProjectRecallRequest struct {
ProjectID string
Question string
Since int64 // unix ms; 0 = the whole history
TopicName string // empty = every topic
// SessionID narrows the search to one conversation. The retrieval pipeline is
// otherwise unchanged, so a session-scoped answer still arrives dated,
// attributed and recency-ranked — which plain session recall does not provide.
SessionID string
Chat ChatClient
}
ProjectRecallRequest is a project-scoped recall query.
type ProjectRecallResult ¶ added in v0.23.0
type ProjectRecallResult struct {
Answer string
Confidence float32
Rounds int
FactsUsed int
SessionsUsed int
TotalFacts int
TotalTopics int
}
ProjectRecallResult is the outcome of a project-scoped recall.
type RecallOptions ¶ added in v0.2.1
type RecallOptions struct {
SessionID string
Question string
MaxRounds int // max refinement rounds, default 3
Threshold float32 // confidence threshold to stop early, default 0.7
Limit int // max facts in lightweight tree, default 50
MinScore float32 // minimum cosine similarity to include fact
Since int64
Until int64
FromOrder int
ToOrder int
// Chat is the synthesis LLM client used for the convergence refinement
// loop. It should be built from the session's selected provider+model.
// When nil, recall returns the raw semantically filtered tree without
// LLM synthesis.
Chat ChatClient
}
type RecallResult ¶ added in v0.2.1
type RelatedConcept ¶ added in v0.2.1
type Scope ¶ added in v0.23.0
Scope identifies the session a memory write belongs to, plus the workspace attributes stamped onto every node so the turn is later recallable at project scope. ProjectID is a project.Resolve'd directory; SessionType mirrors the session store's type ("", "plan", "subagent", …).
type SearchResult ¶ added in v0.2.1
SearchResult pairs a Document with a relevance score.
type SessionMeta ¶ added in v0.2.1
type SessionMeta struct {
ID string `json:"id"`
ProjectID string `json:"projectId,omitempty"`
SessionType string `json:"sessionType,omitempty"`
Name string `json:"name,omitempty"`
CreatedAt int64 `json:"createdAt"`
LastAccessAt int64 `json:"lastAccessAt"`
NodeCount int `json:"nodeCount"`
TopicCount int `json:"topicCount"`
ConceptCount int `json:"conceptCount"`
FactCount int `json:"factCount"`
}
SessionMeta is the metadata for a session.
type SessionUpsert ¶ added in v0.23.0
SessionUpsert carries the session attributes a write path knows about. Empty fields are ignored on update, so a caller that only knows the session ID cannot blank out a project association recorded earlier.
type Store ¶ added in v0.2.1
type Store struct {
// contains filtered or unexported fields
}
Store is the SQLite-backed knowledge graph. All methods are safe for concurrent use; writes are serialized through a mutex.
func (*Store) AddNode ¶ added in v0.2.1
AddNode inserts a node. If a node with the same (session_id, key) exists, it is updated (upsert). Returns the node with its ID set.
func (*Store) BackfillProject ¶ added in v0.23.0
BackfillProject stamps project_id/session_type onto rows written before those columns existed. sessionTypes maps session ID → session type for every session belonging to the project; only rows whose project_id is still empty are touched, so this is idempotent and never re-homes a session.
func (*Store) DeleteEdge ¶ added in v0.2.1
DeleteEdge removes an edge by from_key + to_key.
func (*Store) DeleteNode ¶ added in v0.2.1
DeleteNode removes a node by session_id + key.
func (*Store) DeleteSession ¶ added in v0.2.1
DeleteSession removes a session and all its data (cascading via FK triggers if present).
func (*Store) Embeddings ¶ added in v0.2.1
Embeddings returns all (key, embedding) pairs for a session.
func (*Store) EnsureSession ¶ added in v0.2.1
EnsureSession creates a session if it does not exist, and updates lastAccessAt. Read paths use this when the session's project is unknown or irrelevant.
func (*Store) EnsureSessionMeta ¶ added in v0.23.0
func (s *Store) EnsureSessionMeta(u SessionUpsert) error
EnsureSessionMeta upserts a session along with whatever attributes the caller knows. Only non-empty attributes overwrite existing values.
func (*Store) GetFirstFact ¶ added in v0.2.1
func (*Store) GetLastFact ¶ added in v0.2.1
func (*Store) ListNodes ¶ added in v0.2.1
ListNodes returns all nodes for a session, optionally filtered by type.
func (*Store) ListNodesFiltered ¶ added in v0.2.1
func (s *Store) ListNodesFiltered(sessionID string, f NodeFilter) ([]Node, error)
ListNodesFiltered returns nodes matching the given bounds.
func (*Store) ListProjectConcepts ¶ added in v0.23.0
ListProjectConcepts returns the concept nodes across a project, most recent first. They give recall a vocabulary for follow-up searches.
func (*Store) ListProjectTopics ¶ added in v0.23.0
func (s *Store) ListProjectTopics(projectID string, f ProjectFilter, limit int) ([]TopicCount, error)
ListProjectTopics returns a project's topics ordered by size. Fact placement uses it to reuse topic names another session already established, so one project does not end up with "Auth System", "Authentication" and "auth" as three unrelated topics.
func (*Store) ListSessions ¶ added in v0.2.1
func (s *Store) ListSessions() ([]SessionMeta, error)
ListSessions returns all sessions ordered by last access.
func (*Store) ProjectFactsAt ¶ added in v0.23.0
func (s *Store) ProjectFactsAt(projectID, sessionID string, orders []int, f ProjectFilter) ([]Node, error)
ProjectFactsAt returns the facts at the given per-session orders. Project recall uses it for neighbour windowing, where "the fact before this one" is only meaningful within the same session.
The caller's ProjectFilter is applied here too: a neighbour is still a fact the user asked to exclude, so a date range or topic restriction must not be escaped by being adjacent to something that matched.
func (*Store) ProjectSessionNames ¶ added in v0.23.0
ProjectSessionNames returns sessionID → name for a project, used to label recalled facts with the conversation they came from.
func (*Store) ProjectStats ¶ added in v0.23.0
ProjectStats returns per-project counts.
func (*Store) ScanProjectFacts ¶ added in v0.23.0
ScanProjectFacts streams every fact in a project through fn along with its decoded embedding (nil when the fact was never embedded).
This is a callback scan rather than a slice return because a project graph can hold orders of magnitude more facts than a session graph: the caller keeps a bounded top-K and per-topic tallies instead of materializing every row.
func (*Store) SetEmbedding ¶ added in v0.2.1
SetEmbedding upserts the embedding for a node key.
type TopicCount ¶ added in v0.23.0
TopicCount is a topic name with how many facts sit under it.
type TopicTree ¶ added in v0.2.1
type TopicTree struct {
Name string `json:"name"`
Concepts []ConceptTree `json:"concepts"`
}
TopicTree is the readable tree for one topic.