diff --git a/pkg/memory/vault.go b/pkg/memory/vault.go index 04a4d8cf6..1b4fe3e15 100644 --- a/pkg/memory/vault.go +++ b/pkg/memory/vault.go @@ -1,3 +1,18 @@ +// Package memory implements an Obsidian-inspired markdown vault for persistent +// agent memory. Notes are plain markdown files with YAML frontmatter for +// metadata (title, tags, aliases, dates). The vault is folder-agnostic: +// organization comes from tags and [[wikilinks]], not directory structure. +// +// The vault generates an auto-maintained _index.md file containing a compact +// overview of all notes, tags, and aliases. This index is injected into the +// agent's system prompt so the LLM can efficiently query memory without +// reading every note. +// +// Key design constraints: +// - No external dependencies (hand-rolled frontmatter parser, pure stdlib) +// - No in-memory caches (reads from disk on demand, <10ms for <100 notes) +// - No mutexes (tools are called sequentially by the agent loop) +// - Backward compatible with the legacy MEMORY.md format package memory import ( @@ -11,18 +26,20 @@ import ( // NoteMeta represents parsed frontmatter metadata from a single markdown note. type NoteMeta struct { - Title string - Created string - Updated string - Tags []string - Aliases []string - RelPath string - Links []string + Title string // Note title from frontmatter, or inferred from filename. + Created string // Creation date in YYYY-MM-DD format. + Updated string // Last modification date in YYYY-MM-DD format. + Tags []string // Classification tags for search and filtering. + Aliases []string // Alternate names for wikilink resolution. + RelPath string // Slash-separated path relative to the vault root. + Links []string // Wikilink targets ([[target]]) extracted from the note body. } // Vault manages the memory vault: scanning, indexing, and searching notes. +// All operations read from disk on demand with no in-memory caching, keeping +// the implementation stateless and safe for sequential tool calls. type Vault struct { - memoryDir string + memoryDir string // Absolute path to the vault root directory. } // NewVault creates a new Vault rooted at the given memory directory. diff --git a/pkg/tools/memory.go b/pkg/tools/memory.go index 0f2ab6037..f397fd14b 100644 --- a/pkg/tools/memory.go +++ b/pkg/tools/memory.go @@ -9,6 +9,9 @@ import ( ) // MemorySaveTool saves a structured note to the memory vault with frontmatter. +// It auto-generates YAML frontmatter (title, created, updated, tags, aliases), +// preserves the original created date when updating an existing note, and +// rebuilds the vault index after every write. type MemorySaveTool struct { vault *memory.Vault } @@ -102,6 +105,10 @@ func (t *MemorySaveTool) Execute(ctx context.Context, args map[string]any) *Tool } // MemorySearchTool searches the memory vault by tags, title, or text content. +// Tags use AND logic (a note must match all specified tags). The text query +// matches case-insensitively against title, tags, and aliases. Results are +// capped at 20 entries and include metadata only — use MemoryRecallTool to +// read full note content. type MemorySearchTool struct { vault *memory.Vault } @@ -179,7 +186,9 @@ func (t *MemorySearchTool) Execute(ctx context.Context, args map[string]any) *To } // MemoryRecallTool recalls specific notes from the memory vault by path or topic. -// Unlike memory_search which returns metadata, memory_recall returns full note content. +// Unlike MemorySearchTool which returns metadata only, MemoryRecallTool returns +// the full note body with frontmatter stripped. When using topic-based recall, +// it searches for matching notes and reads the top N (default 3). type MemoryRecallTool struct { vault *memory.Vault }