service

package
v0.5.9 Latest Latest
Warning

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

Go to latest
Published: Jul 6, 2026 License: AGPL-3.0 Imports: 26 Imported by: 0

Documentation

Index

Constants

View Source
const DefaultPerSection = 5

DefaultPerSection is the briefing cap applied to any section whose dedicated opt is nil. It mirrors the historical "per_section=N" default so callers that don't pass per-section options see the same behavior.

Variables

View Source
var ErrInvalidInput = errors.New("invalid input")

ErrInvalidInput marks errors caused by the caller's request (missing fields, unknown tiers) as opposed to backend failures. API layers map it to 400; anything else is a server-side error.

Functions

func RecallPoolSize added in v0.0.6

func RecallPoolSize(k int) int

RecallPoolSize is the per-leg candidate pool Recall over-fetches for a final result count of k, with the default pool sizing. Exported so external pipelines (bench) that re-create recall stage-by-stage match production instead of hardcoding the constants.

Types

type AnswerInput added in v0.0.4

type AnswerInput struct {
	Namespace string
	Query     string
	// Limit caps how many recalled memories are given to the reader (default 10).
	Limit int
	Tiers []memory.Tier
	// Tags / Metadata narrow the grounding recall the same way as Recall: a
	// memory must carry every listed tag and match each metadata key=value pair.
	Tags     []string
	Metadata map[string]string
	// Reasoning selects the answer strategy: empty/minimal is single-shot;
	// low/medium/high run the bounded tool loop (see ReasoningLevel). Falls
	// back to single-shot when the configured LLM client can't do tool calls.
	Reasoning ReasoningLevel
}

AnswerInput is a retrieve-then-generate request.

type AnswerResult added in v0.0.4

type AnswerResult struct {
	Answer  string
	Sources []store.Scored
}

AnswerResult is the generated answer and the memories it was grounded on.

type Briefing added in v0.0.11

type Briefing struct {
	Namespace  string           `json:"namespace"`
	Facts      []*memory.Memory `json:"facts,omitempty"`      // semantic, highest-retention first
	Procedures []*memory.Memory `json:"procedures,omitempty"` // procedural, highest-retention first
	Recent     []*memory.Memory `json:"recent,omitempty"`     // episodic, newest first
	Pinned     []*memory.Memory `json:"pinned,omitempty"`     // tagged pinned, any tier
}

Briefing is a layered session-start summary of a namespace: the most durable facts and procedures, the most recent episodic activity, and pinned memories.

type BriefingOpts added in v0.4.4

type BriefingOpts struct {
	Pinned     *int
	Facts      *int
	Procedures *int
	Recent     *int
}

BriefingOpts sets per-section caps for a Briefing. A nil field falls back to DefaultPerSection (5); a pointer to 0 explicitly disables the section so callers can opt sections out without rebalancing the others. Section caps are independent: pinned memories count against Pinned and never against Facts/Procedures/Recent, so an operator can keep a small durable "top-of-mind" set always-injected while still capping the per-section recall.

type ConsolidateMode

type ConsolidateMode string

ConsolidateMode selects how the opt-in LLM consolidation pipeline runs.

const (
	// ConsolidateAsync stores writes immediately and consolidates in the
	// background — writes never block on the LLM. The default.
	ConsolidateAsync ConsolidateMode = "async"
	// ConsolidateSync consolidates before returning, so a write reflects its
	// dedup/supersede outcome immediately (read-your-consolidated-writes).
	ConsolidateSync ConsolidateMode = "sync"
	// ConsolidateOff disables consolidation even when a consolidator is set.
	ConsolidateOff ConsolidateMode = "off"
)

type DedupInput added in v0.0.8

type DedupInput struct {
	// Similarity gates cluster membership. 0 falls back to the package
	// default (0.85). Negative disables the pass and Dedup returns an empty
	// report without erroring.
	Similarity float64
	// MinClusterSize is the smallest cluster acted on. 0 falls back to 2.
	MinClusterSize int
	// Tiers restricts the pass to these tiers; nil/empty means all tiers.
	Tiers []memory.Tier
	// Namespaces restricts the pass to these namespaces; nil/empty means every
	// namespace. API callers scope this to the request's namespace; only an
	// explicit all-namespaces request leaves it empty.
	Namespaces []string
	// NeighboursPerAnchor bounds the per-anchor vector-search fan-out.
	// 0 falls back to 20.
	NeighboursPerAnchor int
	// DryRun reports what would be done without tombstoning anything.
	DryRun bool
}

DedupInput configures a dedup pass invoked through the service. The zero value is valid and means "use the production defaults": 0.85 similarity, cluster size >= 2, all tiers, 20 neighbours per anchor, dry-run = false.

type ListInput

type ListInput struct {
	Namespace string
	Tiers     []memory.Tier
	// Tags narrows the listing to memories carrying every listed tag (AND).
	Tags []string
	// Metadata narrows the listing to memories whose top-level metadata contains
	// each listed key=value string pair (AND).
	Metadata          map[string]string
	IncludeExpired    bool
	IncludeSuperseded bool
	// Limit caps the result count; <= 0 returns all matches.
	Limit int
	// AllNamespaces lists across every namespace instead of in.Namespace, with
	// Limit applied as a single global cap (newest first). Backs the admin UI's
	// "All projects" view.
	AllNamespaces bool
}

ListInput selects a slice of a namespace's memories for browsing. The zero value (besides Namespace) lists all live memories, newest store order.

type MergeHint added in v0.4.19

type MergeHint struct {
	// SimilarID is the id of the near-duplicate memory. Empty when unknown.
	SimilarID string
	// SimilarContent is a preview of the near-duplicate memory's content.
	SimilarContent string
	// Score is the fused similarity (0..1) between the new write and the
	// near-duplicate.
	Score float64
	// Tier is the tier of the near-duplicate.
	Tier memory.Tier
}

MergeHint surfaces a near-duplicate the caller may want to merge into.

type Metrics

type Metrics interface {
	// ConsolidateResult records one consolidation outcome: one of
	// "gated", "new", "update", "supersede", "noop", "error", "dropped".
	ConsolidateResult(result string)
	// ConsolidateQueueDepth reports the current async queue depth.
	ConsolidateQueueDepth(depth int)
	// RememberResult records the outcome of a Remember call: result is
	// "ok"|"error" and tier is the memory's tier.
	RememberResult(result, tier string)
	// RecallResult records the outcome of a Recall call. result is
	// "ok"|"error"; tierFilter is one of "all"|"working"|"episodic"|
	// "semantic"|"procedural"|"mixed"; hitsBucket is a pre-bucketed
	// count of returned memories: "0"|"1"|"2-5"|"6-20"|"21+".
	RecallResult(result, tierFilter, hitsBucket string)
	// ForgetResult records the outcome of a Forget call: "ok"|"not_found"|"error".
	ForgetResult(result string)
	// SupersedeResult records the outcome of a Supersede call:
	// "ok"|"not_found"|"error". Supersede tombstones a memory (sets
	// superseded_by) rather than deleting it; the maintenance sweeper
	// hard-deletes tombstoned rows after TombstoneTTL.
	SupersedeResult(result string)
	// PromoteResult records one Promote batch: result is "ok"|"error";
	// facts is the number of semantic facts written.
	PromoteResult(result string, facts int)
	// FsckResult records one fsck pass: "ok"|"error". Counters for the
	// work done (purged, evicted, duplicate groups) are exposed separately
	// via the store's maintenance metrics.
	FsckResult(result string)
	// OpDuration observes end-to-end latency for a public operation
	// (e.g. "recall", "answer").
	OpDuration(op string, d time.Duration)
	// AnswerResult records one Answer call: "ok" or "error".
	AnswerResult(result string)
	// RerankResult records one recall rerank attempt: backend is the reranker's
	// label ("llm"|"cross_encoder"); result is "ok" or "fallback".
	RerankResult(backend, result string)
	// RecallDegraded records one recall that fell back to keyword-only search
	// because the query embed failed or timed out. reason is "embed_timeout" or
	// "embed_error".
	RecallDegraded(reason string)
	// WriteSanitized records one ingestion content-hygiene action: "cleaned"
	// (unambiguous corruption stripped from content) or "quarantined"
	// (script-salad downranked when corruption quarantine is enabled).
	WriteSanitized(action string)
	// ReinforceResult records one best-effort recall reinforcement write:
	// "ok" or "error".
	ReinforceResult(result string)
	// DedupTombstoned records the total memories tombstoned by one one-shot
	// Service.Dedup call. Called once per call.
	DedupTombstoned(n int)
	// CorroborateResult records one corroboration-routing attempt on a fresh
	// short-term write: "corroborated" (durable fact reinforced), "cooldown"
	// (match found but inside the per-fact window), "miss" (no durable
	// neighbour at or above the threshold), or "error".
	CorroborateResult(result string)
	// ContradictResult records one contradiction-routing attempt on a fresh
	// durable write: "contradicted" (stale fact invalidated), "no_signal" (a
	// near neighbour, but the detector saw no value/polarity change), "cooldown"
	// (match inside the per-fact window), "miss" (no durable neighbour at or
	// above the threshold, or an untracked-confidence row), or "error".
	ContradictResult(result string)
	// TierClassified records an omitted-tier write the marker classifier
	// routed to a durable tier; tier is "semantic" or "procedural".
	TierClassified(tier string)
}

Metrics receives service-level events for observability. Methods must be safe for concurrent use; a nil Metrics is replaced by a no-op.

type Option

type Option func(*Service)

Option customizes a Service.

func WithAnswerer added in v0.0.4

func WithAnswerer(c llm.Completer) Option

WithAnswerer enables Answer: recall memories, then generate a grounded answer from them with this chat client.

func WithClock

func WithClock(now func() time.Time) Option

WithClock overrides the time source (tests).

func WithConsolidateMinScore

func WithConsolidateMinScore(minScore float64) Option

WithConsolidateMinScore sets the similarity gate: the LLM is only consulted when the nearest candidate scores at least minScore. 0 disables the gate.

func WithConsolidateMode

func WithConsolidateMode(m ConsolidateMode) Option

WithConsolidateMode selects async (default), sync, or off.

func WithConsolidator

func WithConsolidator(c llm.Consolidator) Option

WithConsolidator enables the opt-in LLM consolidation pipeline.

func WithContradictionDownrank added in v0.5.6

func WithContradictionDownrank(minScore float64) Option

WithContradictionDownrank enables contradiction routing: a fresh durable write whose nearest durable neighbour scores at or above minScore, and which the lexical detector (internal/contradict) confirms is a value/polarity change rather than a restatement, invalidates that stale neighbour — stamping its valid_to (so it leaves live recall but stays reachable via AsOf) and shrinking its confidence, off the request path and rate-limited by contradictCooldown. The new write is stored unchanged. minScore <= 0 disables.

func WithCorroboration added in v0.5.4

func WithCorroboration(minScore float64) Option

WithCorroboration enables corroboration routing: a fresh short-term write whose nearest durable neighbour scores at or above minScore reinforces that fact and grows its confidence (rate-limited by corroborateCooldown) instead of only piling up as chatter. The write is still stored. minScore <= 0 disables.

func WithCorruptionQuarantine added in v0.4.11

func WithCorruptionQuarantine(on bool) Option

WithCorruptionQuarantine toggles downranking of writes whose content looks like script-salad — garbled multilingual output from an upstream model or harness glitch (off by default). When on, a flagged write is still stored but has its importance zeroed and metadata.quarantined set, so it sinks in recall instead of surfacing verbatim. It is a heuristic and can misjudge rare legitimate mixed-script text, so it only downranks (never rejects); leave it off unless garbled digests are a problem for a deployment.

func WithDistillBatch added in v0.5.9

func WithDistillBatch(maxTokens int, maxAge time.Duration) Option

WithDistillBatch batches distill-on-write per (namespace, session_id): captures accumulate until their estimated tokens reach maxTokens or the oldest has waited maxAge, then distill as one LLM call with cross-turn context. maxTokens <= 0 disables batching (per-capture distill); captures without a session_id always use the per-capture path. Crash-safe by construction: sources are already durably stored and are stamped promoted_at only at flush, so a lost buffer stays eligible for the batch promoter.

func WithDistillDropNoFact added in v0.4.14

func WithDistillDropNoFact(on bool) Option

WithDistillDropNoFact, with WithDistillOnWrite, deletes an episodic capture when distillation extracts no durable fact. Off by default; not wired to a server flag (the server always keeps episodic captures).

func WithDistillOnWrite added in v0.4.14

func WithDistillOnWrite(on bool) Option

WithDistillOnWrite distils each fresh episodic capture into durable facts at write time. No-op without a distiller, so the server always enables it and lets LLM presence decide whether it runs.

func WithDistiller

func WithDistiller(d llm.Distiller) Option

WithDistiller enables episodic→semantic promotion via RunPromoter.

func WithEpisodicMinChars added in v0.4.14

func WithEpisodicMinChars(n int) Option

WithEpisodicMinChars drops episodic writes whose substantive content is below n characters. 0 (the default) disables it. See MEMINI_EPISODIC_MIN_CHARS.

func WithExtractOnWrite added in v0.4.20

func WithExtractOnWrite(on bool) Option

WithExtractOnWrite runs each fresh episodic capture through the no-LLM heuristic extractor. Only fires when no distiller is configured, so the server always enables it and lets LLM absence decide whether it runs.

func WithFingerprintDedup added in v0.2.9

func WithFingerprintDedup(on bool) Option

WithFingerprintDedup toggles exact-restatement dedup: when on (the default), a fresh write whose normalized content exactly matches a live same-tier memory reinforces that memory instead of storing a duplicate, without embedding it. It is independent of WithWriteDedup (the fuzzy vector gate) and the LLM consolidation pipeline.

func WithGlobalNamespace added in v0.4.20

func WithGlobalNamespace(ns string) Option

WithGlobalNamespace sets a namespace whose durable (semantic/procedural) memories are merged read-only into every other namespace's recall and briefing — a shared space for cross-project rules. Empty disables it.

func WithIDGenerator

func WithIDGenerator(gen func() string) Option

WithIDGenerator overrides ID generation (tests).

func WithMetrics

func WithMetrics(m Metrics) Option

WithMetrics installs an observability sink for consolidation events.

func WithPromoteMinAccess

func WithPromoteMinAccess(n int) Option

WithPromoteMinAccess sets the minimum access_count for an episodic memory to be eligible for promotion.

func WithQueryPrefix

func WithQueryPrefix(p string) Option

WithQueryPrefix prepends an instruction to recall queries before embedding (e.g. the retrieval instruct expected by Qwen3-Embedding or bge models). Documents keep bare embeddings; the keyword leg keeps the raw query.

func WithRecallEmbedTimeout added in v0.4.0

func WithRecallEmbedTimeout(d time.Duration) Option

WithRecallEmbedTimeout bounds the query embed on the recall path. Past the deadline, or on any embed error, recall degrades to keyword-only search rather than failing or stalling on a slow embeddings backend. d <= 0 keeps the query embed unbounded and an embed error fatal (the default).

func WithRecallMinScore added in v0.4.3

func WithRecallMinScore(minScore float64) Option

WithRecallMinScore sets an absolute relevance floor on the fused score: candidates below the threshold are dropped before composite re-ranking and before the reranker. 0 (the default) disables filtering. For score fusion (alpha >= 0) the fused score is in [0,1]; for RRF it is a small rank-based value (~0.016 for the top position). Baked to 0.1 by the server; the benchmark harness overrides it via this Option.

func WithRecallMinSemanticScore added in v0.4.13

func WithRecallMinSemanticScore(minSemanticScore float64) Option

WithRecallMinSemanticScore sets an absolute relevance floor on the raw vector (semantic) score: a candidate below the floor is excluded entirely, so the keyword leg cannot reintroduce an off-topic memory on a shared token. 0 (the default) disables it. The usable value is embedder-dependent; baked to 0 (off) by the server, overridden by the benchmark harness via this Option.

func WithRecallPool

func WithRecallPool(factor, floor int) Option

WithRecallPool overrides the per-leg candidate pool sizing (max(k*factor, floor)) for hybrid recall. Non-positive values keep the defaults. Used by the benchmark harness to sweep pool depth.

func WithRecallSemanticReserve added in v0.4.14

func WithRecallSemanticReserve(n int) Option

WithRecallSemanticReserve reserves up to n of the recall slots for durable tiers (semantic/procedural); a durable takes a slot only when it is relevance-competitive with the entry it displaces (reservePromoteRatio). 0 (the default) disables it. Baked to 2 by the server; the benchmark harness overrides it via this Option.

func WithReinforceSkipMarkers added in v0.4.12

func WithReinforceSkipMarkers(on bool) Option

WithReinforceSkipMarkers drops session-end / stop marker memories from recall reinforcement. The pre-tool-use hook searches once per edited file, so markers would otherwise inflate their access_count and TTL out of proportion. They stay searchable; only the reinforce write is skipped.

func WithRerankTimeout added in v0.2.11

func WithRerankTimeout(d time.Duration) Option

WithRerankTimeout bounds a single reranker call; at the deadline recall degrades to composite order. d <= 0 keeps the default.

func WithReranker added in v0.0.4

func WithReranker(r rerank.Reranker, name string) Option

WithReranker enables reranking of recall candidates: after composite ranking, the top k candidates are reordered by the reranker (an LLM or cross-encoder model), then truncated to the limit. name labels the backend in metrics. It adds one reranker call per Recall, so it is opt-in; a failed rerank falls back to the composite order.

func WithReserveGatePercentile added in v0.5.5

func WithReserveGatePercentile(pct float64) Option

WithReserveGatePercentile (pct > 0) switches the reserve's relevance gate to the adaptive form: a durable takes a reserved slot only when its composite score reaches the pct-th percentile of the window's own scores, so the bar derives from the pool's score distribution instead of a fixed ratio. Tuning/bench knob (bench/reserve_sweep_test.go); 0 keeps the ratio gate.

func WithReservePromoteRatio added in v0.5.5

func WithReservePromoteRatio(ratio float64) Option

WithReservePromoteRatio overrides the evictee-relative leg of the reserve's relevance gate: a durable takes a reserved slot only when its composite score is at least ratio× the entry it evicts. Tuning/bench knob (bench/reserve_sweep_test.go); the production default is defaultReservePromoteRatio.

func WithReserveTopAnchor added in v0.5.5

func WithReserveTopAnchor(anchor float64) Option

WithReserveTopAnchor overrides the absolute leg of the reserve's relevance gate: a durable takes a reserved slot only when its composite score is at least anchor× the window's top hit. Tuning/bench knob (bench/reserve_sweep_test.go); the production default is defaultReserveTopAnchor, and 0 disables the leg.

func WithScoreFusion

func WithScoreFusion(alpha float64) Option

WithScoreFusion sets the hybrid fusion weight: the vector leg by alpha and the keyword leg by 1-alpha (score fusion). alpha < 0 selects rank fusion (RRF). The package default is score fusion at DefaultFusionAlpha.

func WithSecretRedaction added in v0.3.8

func WithSecretRedaction(on bool) Option

WithSecretRedaction toggles server-side scrubbing of live credentials from a memory's Content/Summary/Metadata at ingestion (on by default). It bounds a database compromise to information disclosure — leaked memory holds no usable tokens, keys, or passwords. Disable only if redaction mangles legitimate content; storing raw secrets re-opens the lateral-movement risk.

func WithShortTermCap

func WithShortTermCap(cap int) Option

WithShortTermCap bounds short-term memories per namespace, enforced by fsck.

func WithSyncReinforce

func WithSyncReinforce() Option

WithSyncReinforce makes recall reinforcement run synchronously (tests).

func WithTemporalTargeting added in v0.0.4

func WithTemporalTargeting(boost float64, ex search.AnchorExtractor) Option

WithTemporalTargeting enables temporal targeting in the re-ranker: when a query names a relative time, candidates dated near the referenced point are boosted by up to `boost` on the composite score. ex resolves the reference (use search.RegexAnchorExtractor{} for the no-LLM default). boost <= 0 or a nil extractor disables it.

func WithWriteDedup

func WithWriteDedup(score float64, action WriteDedupAction) Option

WithWriteDedup configures write-time dedup: when a fresh write's nearest same-tier memory scores at or above score, the given action fires (see WriteDedupAction). A score of 0 or action "off" disables it. This replaces the former three-gate band system — there is no ordering to misconfigure.

type ReasoningLevel added in v0.5.9

type ReasoningLevel string

ReasoningLevel selects the answer strategy: empty/minimal is the single-shot recall+complete path; low/medium/high run a bounded tool loop where the model may search memory again before answering — the latency/cost dial for multi-hop and temporal questions.

const (
	ReasoningMinimal ReasoningLevel = "minimal"
	ReasoningLow     ReasoningLevel = "low"
	ReasoningMedium  ReasoningLevel = "medium"
	ReasoningHigh    ReasoningLevel = "high"
)

type RecallInput

type RecallInput struct {
	Namespace string
	Query     string
	Tiers     []memory.Tier
	// Tags narrows recall to memories carrying every listed tag (AND).
	Tags []string
	// Metadata narrows recall to memories whose top-level metadata contains each
	// listed key=value string pair (AND).
	Metadata map[string]string
	// ExcludeMetadata drops memories whose top-level metadata contains every
	// listed key=value pair (AND), applied after Metadata. Lets a caller exclude
	// its own session's just-captured turns from auto-recall.
	ExcludeMetadata map[string]string
	Limit           int
	// IncludeExpired / IncludeSuperseded relax the default live-only filter.
	IncludeExpired    bool
	IncludeSuperseded bool
	// AsOf, when non-zero, runs time-travel recall: it returns the facts whose
	// validity window contained AsOf (including ones since superseded), instead
	// of only currently-live memories.
	AsOf time.Time
	// Subtree expands recall to Namespace and every namespace nested under it
	// ("project" also reads "project/agent-a", "project/agent-b", ...), for the
	// multi-agent "read shared + private" pattern. Default (false) is exact scope,
	// so cross-agent recall never happens unless asked for.
	Subtree bool
	// MinScore, when > 0, overrides the server's default recallMinScore for
	// this call. Lets a caller request a stricter relevance floor per
	// integration (e.g. the pre-tool-use hook only injects highly-relevant
	// hits). 0 (the zero value) falls back to the server-wide gate. Only
	// meaningful with score fusion; RRF scores are not comparable to [0,1].
	MinScore float64
	// MinSemanticScore, when > 0, overrides the server's default
	// recallMinSemanticScore (the absolute vector-relevance gate) for this call.
	// 0 falls back to the server-wide gate.
	MinSemanticScore float64
	// SemanticReserve, when > 0, overrides the server's default
	// recallSemanticReserve (durable-tier slot reservation) for this call. 0
	// falls back to the server-wide value.
	SemanticReserve int
}

RecallInput describes a hybrid recall query.

type RememberInput

type RememberInput struct {
	Namespace  string
	Content    string
	Tier       memory.Tier
	Summary    string
	Tags       []string
	Metadata   map[string]any
	Importance float64
	// TTL overrides the tier default. A negative TTL means "never expire".
	TTL *time.Duration
	// ID upserts an existing memory when set; otherwise a new ID is generated.
	ID string
	// Confidence overrides the seed corroboration for a durable fact (e.g. a
	// trusted import). nil uses the default seed. Ignored for short-term tiers.
	Confidence *float64
	// ValidFrom / ValidTo set the interval the fact was true, for recording
	// historical facts that time-travel (AsOf) recall can surface. ValidFrom
	// defaults to now (or the existing row on update); ValidTo defaults to open.
	ValidFrom *time.Time
	ValidTo   *time.Time
	// MergeHint (output-only) is set to a non-nil MergeHint when the write's
	// nearest same-tier candidate landed in the merge-hint band. The caller
	// passes the address of a local `*MergeHint`; after the call it holds the
	// hint (or remains nil). nil disables hint reporting.
	MergeHint *MergeHint
	// AutoSuperseded (output-only) is set to true when the write triggered a
	// background supersede. The caller passes the address of a local bool.
	// nil disables reporting.
	AutoSuperseded *bool
}

RememberInput describes a memory to store. Only Namespace and Content are required; an omitted Tier is classified from the content (episodic when unclear) and TTL follows the tier default.

type Service

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

Service wires storage and embeddings together. It is safe for concurrent use.

func New

func New(st store.Store, e embed.Embedder, opts ...Option) *Service

New builds a Service from a store and embedder.

func (*Service) Answer added in v0.0.4

func (s *Service) Answer(ctx context.Context, in AnswerInput) (AnswerResult, error)

Answer recalls memories for the query and asks the configured LLM to answer from them, grounding the response and returning the supporting memories. It requires an answerer (see WithAnswerer); recall reuses the full hybrid + rerank path, so a configured reranker applies here too.

func (*Service) Briefing added in v0.0.11

func (s *Service) Briefing(ctx context.Context, namespace string, opts BriefingOpts) (Briefing, error)

Briefing builds a session-start briefing for a namespace: up to Facts semantic facts (ranked by DurableScore), Procedures procedural how-tos, Recent episodic entries (newest first), and Pinned pinned memories (any tier). Each opt is a pointer so nil falls back to DefaultPerSection and a pointer to 0 disables the section. It is a cheap, query-less read for hooks to inject context when a session opens.

func (*Service) Dedup added in v0.0.8

Dedup runs a vector-cluster dedup pass: each cluster's representative (the member with the highest RetentionScore) is kept; the rest are tombstoned (SupersededBy → representative) so they're hidden from default search results. The action is reversible. With in.Namespaces empty the pass spans every namespace; callers usually scope it to one.

It's mainly a post-import cleanup tool, since exports tend to be full of restatements. The default similarity (0.85) is a paraphrase-level threshold; raise it for stricter, lower it for looser merging.

func (*Service) DeleteNamespace added in v0.0.8

func (s *Service) DeleteNamespace(ctx context.Context, namespace string) (int64, error)

DeleteNamespace removes every memory in a namespace. Returns the number of memories deleted.

func (*Service) FlushConsolidation added in v0.5.9

func (s *Service) FlushConsolidation(ctx context.Context) error

FlushConsolidation blocks until every consolidation job queued before the call has been processed. It is a no-op without an async consolidator, and needs StartConsolidator running (otherwise it waits until ctx is done). Intended for benches and tests that must let consolidation settle before measuring.

func (*Service) Forget

func (s *Service) Forget(ctx context.Context, namespace, id string) error

Forget deletes a memory by ID.

func (*Service) ForgetByTag added in v0.0.11

func (s *Service) ForgetByTag(ctx context.Context, namespace, tag string) (int64, error)

ForgetByTag deletes every memory in a namespace carrying tag, including superseded and expired ones, and returns the count deleted. With the import provenance tag (import:<source>:<date>), this undoes a bulk import in one call.

func (*Service) Fsck

func (s *Service) Fsck(ctx context.Context) (maintenance.Report, error)

Fsck runs a consistency sweep: purge expired, enforce the short-term cap, and audit live memories for duplicate clusters.

func (*Service) Get

func (s *Service) Get(ctx context.Context, namespace, id string) (*memory.Memory, error)

Get returns a single memory by ID.

func (*Service) History added in v0.4.19

func (s *Service) History(ctx context.Context, namespace, id string) ([]*memory.Memory, error)

History returns the full supersession lineage of a memory: the memory itself, every memory it superseded (walking PredecessorIDs backwards) and every one that superseded it (following SupersededBy forwards), including tombstoned rows, ordered oldest-first by CreatedAt. Returns ErrNotFound when id is absent. Walks breadth-first so a merge (several memories superseded by one) is followed in every direction without revisiting a node.

func (*Service) List

func (s *Service) List(ctx context.Context, in ListInput) ([]*memory.Memory, error)

List returns memories in a namespace matching the filter, without embeddings. It backs the UI memory browser and the client-derived relationship graph.

func (*Service) Namespaces

func (s *Service) Namespaces(ctx context.Context) ([]string, error)

Namespaces returns the distinct namespaces holding memories, for the UI tenant switcher.

func (*Service) Promote

func (s *Service) Promote(ctx context.Context) (int, error)

Promote distills frequently-accessed, not-yet-promoted episodic memories in each namespace into durable semantic facts (written via Remember so they get the similarity gate and consolidation dedup), then stamps the sources so they aren't reprocessed. Without a distiller it falls back to the marker extractor, so usage-earned promotion also works on LLM-less deployments. Returns the number of facts written.

func (*Service) Recall

func (s *Service) Recall(ctx context.Context, in RecallInput) ([]store.Scored, error)

func (*Service) Remember

func (s *Service) Remember(ctx context.Context, in RememberInput) (*memory.Memory, error)

Remember embeds and stores a memory, returning the persisted record.

func (*Service) RunPromoter

func (s *Service) RunPromoter(ctx context.Context, interval time.Duration)

RunPromoter periodically distills frequently-accessed episodic memories into durable semantic facts until ctx is cancelled. It is a no-op without a positive interval. Call once, typically in its own goroutine.

func (*Service) StartConsolidator

func (s *Service) StartConsolidator(ctx context.Context)

StartConsolidator runs the background consolidation worker until ctx is cancelled, then drains queued jobs within a bounded timeout. It is a no-op unless the service was built with a consolidator in async mode. Call once, typically in its own goroutine.

func (*Service) StartDistillBatcher added in v0.5.9

func (s *Service) StartDistillBatcher(ctx context.Context)

StartDistillBatcher runs the age-flush loop for batched distill-on-write until ctx is cancelled, then flushes every remaining buffer. A no-op unless the service was built with WithDistillBatch. Call once, typically in its own goroutine (mirrors StartConsolidator).

func (*Service) Stats

func (s *Service) Stats(ctx context.Context, namespace string) (Stats, error)

Stats computes a per-namespace overview by scanning all of its memories (including expired and superseded, so those can be counted separately).

func (*Service) StatsAll added in v0.0.10

func (s *Service) StatsAll(ctx context.Context) (Stats, error)

StatsAll merges per-namespace overviews into a single store-wide one (namespace reported as ""), backing the admin UI's "All projects" dashboard.

func (*Service) Supersede added in v0.4.12

func (s *Service) Supersede(ctx context.Context, namespace, id, supersededBy string) error

Supersede tombstones (namespace, id), recording that it was replaced by supersededBy. The row is hidden from default recall but kept for the audit/time-travel chain; the sweeper hard-deletes it after TombstoneTTL. NotFound surfaces to the caller so a missing target is not silently swallowed. Idempotent: re-superseding overwrites superseded_by.

func (*Service) WaitBackground added in v0.0.6

func (s *Service) WaitBackground()

WaitBackground blocks until detached background goroutines (async recall reinforcement) finish. Call during shutdown, after the workers have been stopped and before closing the store.

type Stats

type Stats struct {
	Namespace    string              `json:"namespace"`
	Total        int                 `json:"total"`                    // live memories (excludes expired/superseded)
	ByTier       map[memory.Tier]int `json:"by_tier"`                  // live count per tier
	ByMemoryType map[string]int      `json:"by_memory_type,omitempty"` // live count per metadata.memory_type (typed extractions)
	Expired      int                 `json:"expired"`                  // past-TTL, not yet swept
	Superseded   int                 `json:"superseded"`               // contradiction-tombstoned
	// uncorroborated durable debris (confidence below the demote floor); unbounded
	// by short-term caps, so a growing value signals reclaimable bloat
	LowConfidenceDurable int        `json:"low_confidence_durable"`
	TotalAccesses        int        `json:"total_accesses"`
	AvgImportance        float64    `json:"avg_importance"`
	LastWriteAt          *time.Time `json:"last_write_at,omitempty"`
}

Stats summarizes a namespace for the UI dashboard. Counts are computed from a full listing, so callers should treat it as a curated-namespace overview, not a hot-path metric (Prometheus /metrics remains the source for operational counters).

type WriteDedupAction added in v0.5.0

type WriteDedupAction string

WriteDedupAction selects what write-time dedup does when a fresh write scores at or above the dedup threshold against its nearest same-tier memory.

const (
	// WriteDedupOff disables write-time fuzzy dedup. The exact-restatement
	// fingerprint pass (WithFingerprintDedup) is independent and still runs.
	WriteDedupOff WriteDedupAction = "off"
	// WriteDedupHint stores the write and returns a MergeHint for the caller to
	// merge. Non-destructive; scoped to durable tiers (semantic/procedural).
	WriteDedupHint WriteDedupAction = "hint"
	// WriteDedupCoalesce reinforces the existing memory and drops the write
	// (headless corpus hygiene). Applies to all tiers.
	WriteDedupCoalesce WriteDedupAction = "coalesce"
	// WriteDedupSupersede stores the write and tombstones the old memory.
	WriteDedupSupersede WriteDedupAction = "supersede"
)

Jump to

Keyboard shortcuts

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