Documentation
¶
Overview ¶
Package memory is tinyagent's cross-run project memory store: short, redacted notes that a run saves about a project and later runs load into their system prompt. A store is either a folder of markdown files (one <id>.md per entry, the default ./memory) or one SQLite database (see backend.go); the legacy per-project JSON file is still read so it can be imported. Entries carry provenance and may be held as pending until a person approves them; pending entries are never rendered into a prompt.
The package has no model, network or config dependency: callers decide when memory is enabled and pass the store path, policy and limits in.
Index ¶
- Constants
- Variables
- func Approve(path, id string, all bool) (int, error)
- func BackendOf(path string) string
- func Exists(path string) bool
- func Forget(path, id string) error
- func ForgetAll(path string) (int, error)
- func ImportLegacy(path, legacy string) (int, error)
- func MarshalMarkdown(e Entry) ([]byte, error)
- func NormalizeTags(tags []string) []string
- func OldDefaultStore(backend, cwd string) string
- func ProjectKey(root string) string
- func ProjectRoot(cwd string) (string, error)
- func RenderLines(lines []Line, omitted int) string
- func ResolveStore(backend, dir, sqlitePath, cwd string) (string, error)
- func StorePath(dir, cwd string) (string, error)
- func Update(path string, fn func([]Entry) ([]Entry, error)) error
- func ValidApproval(s string) bool
- func ValidBackend(s string) bool
- type CorruptError
- type Entry
- type Limits
- type Line
- type Rendered
- type Result
- type Saved
- type Source
- type Writer
- func (w *Writer) Add(text string) (Result, error)
- func (w *Writer) AddTagged(text string, tags []string) (Result, error)
- func (w *Writer) Forget(id string) (Result, error)
- func (w *Writer) MarkUntrusted()
- func (w *Writer) Replace(id, text string) (Result, error)
- func (w *Writer) TakeSaved() []Saved
- func (w *Writer) Untrusted() bool
- func (w *Writer) Writes() int
Constants ¶
const ( BackendMarkdown = "markdown" BackendSQLite = "sqlite" )
Store backends. A store is named by one path, and its kind follows from that path: a .sqlite, .sqlite3 or .db file is a SQLite database, a .json file is a legacy JSON store (read for import, still writable), and anything else is a markdown folder holding one <id>.md file per entry.
const ( DefaultMarkdownPath = ".tinyagent/memory" DefaultSQLitePath = ".tinyagent/memory/memory.sqlite" )
Default store locations, relative to the working directory (issue #335: memory lives only under ./.tinyagent/memory in --cwd).
const ( StatusActive = "active" StatusPending = "pending" )
Entry statuses.
const ( // ApprovalPending saves every new entry as pending. ApprovalPending = "pending" // ApprovalAuto saves new entries as active unless the run had untrusted // content in context. ApprovalAuto = "auto" )
Approval policies for new entries.
const ( DefaultMaxWritesPerRun = 5 DefaultMaxEntries = 50 DefaultMaxBytes = 8 * 1024 // MaxTextLen is the longest entry text, in characters. MaxTextLen = 500 )
Default limits.
Variables ¶
var ErrNotFound = errors.New("no memory entry with that id")
ErrNotFound is returned for an id that isn't in the store.
var ErrOutsideCwd = errors.New("memory store must stay inside --cwd")
ErrOutsideCwd marks a store path that was refused because it would leave the working directory (issue #335).
Functions ¶
func Approve ¶
Approve activates the pending entry id, or every pending entry when all is true, and returns how many were approved. Approving a pending replacement removes the active entry it replaces.
func Exists ¶
Exists reports whether the store at path exists (a folder for markdown, a file otherwise).
func Forget ¶
Forget removes entry id (active or pending), along with any pending replacement of it.
func ForgetAll ¶
ForgetAll removes every entry and returns how many there were. A missing store stays missing.
func ImportLegacy ¶
ImportLegacy copies the entries of the legacy JSON store at legacy (the pre-markdown per-project file, see StorePath) into the store at path, once: only when path doesn't exist yet and legacy holds entries. It never changes or deletes legacy, and returns how many entries it copied. Once the new store exists (even emptied by --memory-forget all), it never imports again.
func MarshalMarkdown ¶
MarshalMarkdown renders e as one markdown file: YAML front matter, then the text as the body.
func NormalizeTags ¶
NormalizeTags lowercases, trims and de-duplicates tags, dropping empty ones. Tags may hold letters, digits and . _ - / : only; anything else becomes "-", so a tag is always one comma-free word.
func OldDefaultStore ¶ added in v0.16.0
OldDefaultStore returns the store the previous default location (./memory in cwd, before issue #335) holds for backend, or "" when there is none. Only cwd is looked at. Callers print a one-line hint; nothing is moved.
func ProjectKey ¶
ProjectKey returns the store file's base name for a project root: a readable name plus a hash of the full path, so two projects with the same directory name never share a store.
func ProjectRoot ¶
ProjectRoot returns the path that identifies cwd's project: the Git common directory when cwd is inside a Git work tree, so the main checkout and every linked worktree share one store, else the absolute cwd. Symlinks are resolved either way.
func RenderLines ¶
RenderLines builds the prompt section from already-selected lines and the number of omitted entries, exactly as Render does. It returns "" when there are no lines and nothing was omitted.
func ResolveStore ¶
ResolveStore returns the absolute store path for backend: dir (markdown) or sqlitePath (sqlite), each defaulting to its Default*Path, resolved against cwd. A path that would leave cwd (absolute, "..", or a symlink pointing outside) is refused with an error wrapping ErrOutsideCwd.
func StorePath ¶
StorePath returns the legacy JSON store file for cwd's project under dir. There is no default directory: since issue #335 tinyagent never looks for memory outside --cwd, so dir must be given.
func Update ¶
Update re-reads the store at path under an exclusive lock, applies fn and writes the result atomically, so concurrent writers never lose each other's changes. If fn returns an error nothing is written. A corrupt store is left unchanged and its *CorruptError is returned.
func ValidApproval ¶
ValidApproval reports whether s is a known approval policy.
func ValidBackend ¶
ValidBackend reports whether s is a selectable backend.
Types ¶
type CorruptError ¶
CorruptError reports a store file that exists but can't be parsed. A corrupt store is never overwritten.
func (*CorruptError) Error ¶
func (e *CorruptError) Error() string
func (*CorruptError) Unwrap ¶
func (e *CorruptError) Unwrap() error
type Entry ¶
type Entry struct {
ID string `json:"id"`
Text string `json:"text"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Source Source `json:"source"`
// Tags are short lowercase labels (memory.default_tags plus any the
// model gave); memory_search can filter by them.
Tags []string `json:"tags,omitempty"`
// Replaces is set on a pending entry that, once approved, replaces the
// active entry with this id.
Replaces string `json:"replaces,omitempty"`
}
Entry is one saved note.
func Active ¶
Active returns the active entries, newest (by UpdatedAt) first; ties keep the later-stored entry first.
func Load ¶
Load reads the store at path, oldest first. A missing store is empty and is never created. A store that can't be parsed returns a *CorruptError.
func Search ¶
Search returns the active entries whose text or tags contain every word of query (case-insensitive) and that carry tag when tag is set, newest first, at most limit (0 means no limit). Pending entries never match: a person hasn't approved them.
func UnmarshalMarkdown ¶
UnmarshalMarkdown parses one markdown entry file. It accepts CRLF line endings, a UTF-8 byte-order mark, blank lines around the body and unknown front-matter keys (ignored).
type Limits ¶
type Limits struct {
MaxWritesPerRun int
MaxEntries int
// MaxTextLen is the longest entry text in characters; 0 means
// MaxTextLen (the package default).
MaxTextLen int
}
Limits bound what one run may write and what the store may hold.
func DefaultLimits ¶
func DefaultLimits() Limits
DefaultLimits returns the default per-run and store limits.
type Line ¶
Line is one loaded entry as it appears in the prompt section: its id, its date (YYYY-MM-DD, UTC) and its text. A run records its loaded lines so a resume can rebuild the identical section without reading the store.
type Rendered ¶
type Rendered struct {
// Section is the text to add to the system prompt, or "" when no entry
// is active.
Section string
// Loaded are the entries in Section, newest first.
Loaded []Entry
// Omitted counts active entries left out to stay within maxBytes.
Omitted int
}
Rendered is the prompt section for one run plus what it contains.
type Result ¶
type Result struct {
Op string `json:"op"`
ID string `json:"id"`
Status string `json:"status"`
Redacted bool `json:"redacted"`
}
Result describes one successful write.
type Saved ¶
Saved is one successful write a Writer made, reported as a memory.saved event: the result plus the entry's source (the untrusted-context flag).
type Source ¶
type Source struct {
RunID string `json:"run_id,omitempty"`
Model string `json:"model,omitempty"`
Version string `json:"version,omitempty"`
UntrustedContext bool `json:"untrusted_context"`
}
Source records where an entry came from.
type Writer ¶
type Writer struct {
Path string
Approval string
Limits Limits
// Redactor masks configured secret values; token-shaped strings are
// always masked, whether or not it is set.
Redactor *eventlog.Redactor
Source Source
// Tags are added to every entry this writer saves (memory.default_tags).
Tags []string
// contains filtered or unexported fields
}
Writer applies one run's memory writes to the store. It enforces the per-run write limit, the store's active-entry limit, the approval policy and redaction. Writes go to the store only; they never change the run's own prompt. It is safe for concurrent use.
func NewWriter ¶
func NewWriter(path, approval string, limits Limits, red *eventlog.Redactor, src Source, snapshot []Entry) *Writer
NewWriter returns a Writer for path whose replace and forget operations may target the ids in snapshot (the entries loaded at run start).
func (*Writer) MarkUntrusted ¶
func (w *Writer) MarkUntrusted()
MarkUntrusted records that untrusted external content (a fetched web page, an MCP result, a review diff) entered the run's context; every later write is saved pending with source.untrusted_context set.
func (*Writer) Replace ¶
Replace changes the text of entry id. When the new text would be pending and id is active, a pending replacement is saved instead and the active entry stays in place until the replacement is approved.