Documentation
¶
Overview ¶
Package memory 提供长期记忆的存储、召回和冲突处理领域模型。
该包不依赖 session 或 turn。Turn 只负责在正确的生命周期边界调用 Service,并把返回的 Snapshot 渲染成 request-only 上下文。
Index ¶
- Constants
- Variables
- type BoundedText
- type Candidate
- type CandidateExtractor
- type CandidatePipeline
- type CandidateSubmitter
- type Conflict
- type ConflictDecision
- type ConsolidationReport
- type Consolidator
- type Entry
- type ExtractionInput
- type ExtractionMessage
- type ExtractionToolCall
- type Kind
- type LLMCandidateExtractor
- type LocalService
- func (s *LocalService) AgentID() string
- func (s *LocalService) ApplyMaintenanceOperation(ctx context.Context, op MaintenanceOperation, candidates []Candidate, ...) ([]WriteResult, error)
- func (s *LocalService) Close() error
- func (s *LocalService) Consolidate(ctx context.Context, candidates []Candidate) ([]WriteResult, error)
- func (s *LocalService) Forget(ctx context.Context, scope Scope, id, reason string) (WriteResult, error)
- func (s *LocalService) Get(ctx context.Context, scope Scope, id string, includeInactive bool) (Entry, error)
- func (s *LocalService) GetMaintenanceCursor(ctx context.Context) (MaintenanceCursor, error)
- func (s *LocalService) GetMaintenanceOperation(ctx context.Context, id string) (MaintenanceOperation, error)
- func (s *LocalService) List(ctx context.Context, scope Scope, includeInactive bool) ([]Entry, error)
- func (s *LocalService) Maintain(ctx context.Context, scope Scope, coreBudget int) (MaintenanceReport, error)
- func (s *LocalService) Recall(ctx context.Context, req RecallRequest) (Snapshot, error)
- func (s *LocalService) Remember(ctx context.Context, req RememberRequest) (WriteResult, error)
- func (s *LocalService) ReplaceAll(ctx context.Context, scope Scope, entries []Entry) error
- func (s *LocalService) ResolveConflict(ctx context.Context, scope Scope, conflictID string, decision ConflictDecision) (WriteResult, error)
- func (s *LocalService) Scope() Scope
- func (s *LocalService) Search(ctx context.Context, req SearchRequest) ([]SearchResult, error)
- func (s *LocalService) SetScope(scope Scope)
- func (s *LocalService) UpdateContent(ctx context.Context, scope Scope, id, content string) (WriteResult, error)
- type Maintainer
- type MaintenanceCursor
- type MaintenanceOperation
- type MaintenanceReport
- type RecallRequest
- type Reference
- type RememberRequest
- type Scope
- type SearchRequest
- type SearchResult
- type Service
- type Snapshot
- type Status
- type Store
- func (s *Store) Close() error
- func (s *Store) GetMaintenanceCursor(ctx context.Context, agentID string) (MaintenanceCursor, error)
- func (s *Store) GetMaintenanceOperation(ctx context.Context, id string) (MaintenanceOperation, error)
- func (s *Store) List(ctx context.Context, includeInactive bool) ([]Entry, error)
- type Tier
- type WriteOutcome
- type WriteResult
Constants ¶
const ( DefaultMemoryContextTokenBudget = 2000 DefaultMemoryCoreTokenBudget = 800 DefaultMemoryRecallTokenBudget = 1200 DefaultMemorySearchLimit = 6 DefaultMemorySearchTokenBudget = 1200 DefaultMemorySearchEntryBudget = 160 DefaultMemoryGetTokenBudget = 2000 DefaultMemoryGetContentBudget = 1500 DefaultMemoryQueryTokenBudget = 160 DefaultMemoryMaxSearchTerms = 24 )
The budgets below are model-visible budgets. Storage is intentionally not bounded by them; only a rendered context or a tool response is bounded.
Variables ¶
var ErrMaintenanceConflict = errors.New("maintenance operation conflict")
var ErrNotFound = errors.New("memory entry not found")
var ErrScopeForbidden = errors.New("memory scope is not permitted")
ErrScopeForbidden means a model-level memory operation attempted to leave the scope configured for the current Agent. Settings and migration use the explicit control-plane methods and may inspect both scopes.
Functions ¶
This section is empty.
Types ¶
type BoundedText ¶
type BoundedText struct {
Text string `json:"text"`
OriginalTokens int `json:"original_tokens"`
ReturnedTokens int `json:"returned_tokens"`
Truncated bool `json:"truncated"`
}
BoundedText is the observable result of clipping text for a model-facing response. OriginalTokens lets the model distinguish a complete value from a preview without receiving the original payload.
func BoundText ¶
func BoundText(text string, maxTokens int) BoundedText
type Candidate ¶
type Candidate struct {
Request RememberRequest `json:"request"`
}
Candidate is model-inferred information awaiting serial consolidation. A candidate is never directly visible to Recall; the consolidator first stages it as pending and only promotes conflict-free candidates.
type CandidateExtractor ¶
type CandidateExtractor interface {
Extract(context.Context, ExtractionInput) ([]Candidate, error)
}
CandidateExtractor is an optional extension point. Implementations must be cancellation-aware and must not mutate the input slice.
type CandidatePipeline ¶
type CandidatePipeline struct {
// contains filtered or unexported fields
}
CandidatePipeline owns a bounded background extraction queue. One pipeline is created per Agent runtime, so its single worker also provides the per-Agent serialization boundary required by the memory contract.
A nil extractor or consolidator makes the pipeline inert. This is the deliberate default: merely enabling Memory v2 does not spend LLM tokens on automatic extraction.
func NewCandidatePipeline ¶
func NewCandidatePipeline( extractor CandidateExtractor, consolidator Consolidator, queueSize int, onError func(error), ) *CandidatePipeline
NewCandidatePipeline creates an optional asynchronous pipeline. queueSize is bounded so compression cannot create unbounded memory work when a model or SQLite store is slow.
func (*CandidatePipeline) Close ¶
func (p *CandidatePipeline) Close() error
Close cancels extraction and prevents late compression callbacks from sending on a closed channel. Extraction implementations must honor ctx.
func (*CandidatePipeline) SetCoreBudget ¶
func (p *CandidatePipeline) SetCoreBudget(tokens int)
func (*CandidatePipeline) SetOnChange ¶
func (p *CandidatePipeline) SetOnChange(fn func(ConsolidationReport))
SetOnChange attaches a metadata-only callback. It is intentionally separate from construction so the runtime can bind its publisher after allocation.
func (*CandidatePipeline) Submit ¶
func (p *CandidatePipeline) Submit(input ExtractionInput) bool
Submit queues a defensive copy and returns false when automatic extraction is disabled or the bounded queue is full. The caller must treat false as a dropped optional background task; the active Turn is never affected.
type CandidateSubmitter ¶
type CandidateSubmitter interface {
Submit(ExtractionInput) bool
}
CandidateSubmitter is the small boundary used by compression. Keeping this interface separate means compression does not know about queues, stores or Turn lifecycle.
type Conflict ¶
type Conflict struct {
ID string `json:"id"`
Candidate Entry `json:"candidate"`
Existing []Entry `json:"existing"`
ExistingRevisions []int64 `json:"existing_revisions"`
Relation string `json:"relation"`
Description string `json:"description"`
StoreRevision int64 `json:"store_revision"`
CreatedAt time.Time `json:"created_at"`
}
type ConflictDecision ¶
type ConflictDecision string
const ( ConflictKeepOld ConflictDecision = "keep_old" ConflictUseNew ConflictDecision = "use_new" ConflictKeepBoth ConflictDecision = "keep_both" ConflictCancel ConflictDecision = "cancel" )
type ConsolidationReport ¶
type Consolidator ¶
type Consolidator interface {
Consolidate(context.Context, []Candidate) ([]WriteResult, error)
}
Consolidator serializes candidate writes for one Agent. It must never approve a conflict automatically; conflicting candidates remain pending.
type Entry ¶
type Entry struct {
ID string `json:"id"`
Scope Scope `json:"scope"`
Tier Tier `json:"tier"`
Kind Kind `json:"kind"`
SemanticKey string `json:"semantic_key,omitempty"`
Subject string `json:"subject,omitempty"`
Predicate string `json:"predicate,omitempty"`
Value any `json:"value,omitempty"`
Qualifiers map[string]string `json:"qualifiers,omitempty"`
Cardinality string `json:"cardinality,omitempty"`
Content string `json:"content"`
NormalizedText string `json:"normalized_content,omitempty"`
ContentHash string `json:"content_hash,omitempty"`
Status Status `json:"status"`
Importance int `json:"importance"`
Confidence int `json:"confidence"`
Sensitivity string `json:"sensitivity,omitempty"`
SourceType string `json:"source_type"`
SourceSession string `json:"source_session_id,omitempty"`
SourceMessage string `json:"source_message_id,omitempty"`
SourceRef string `json:"source_reference,omitempty"`
SupersedesID string `json:"supersedes_id,omitempty"`
ConflictGroup string `json:"conflict_group_id,omitempty"`
ValidFrom *time.Time `json:"valid_from,omitempty"`
ValidTo *time.Time `json:"valid_to,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
Revision int64 `json:"revision"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LastAccessedAt *time.Time `json:"last_accessed_at,omitempty"`
AccessCount int64 `json:"access_count"`
}
Entry 是一条结构化长期记忆。结构化字段允许 Repository 先做确定性 去重/冲突判断,content 仍然保留模型可读的原始正文。
type ExtractionInput ¶
type ExtractionInput struct {
AgentID string `json:"agent_id"`
SessionID string `json:"session_id"`
Scope Scope `json:"scope,omitempty"`
SourceFingerprint string `json:"source_fingerprint"`
Messages []ExtractionMessage `json:"messages"`
SkipOnly bool `json:"skip_only,omitempty"`
SkippedThrough int64 `json:"skipped_through,omitempty"`
}
ExtractionInput is a frozen, bounded source for background memory extraction. SourceFingerprint ties any candidate back to the exact compression slice without storing the slice in the memory database.
type ExtractionMessage ¶
type ExtractionMessage struct {
Role string `json:"role"`
Name string `json:"name,omitempty"`
Content string `json:"content,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
ToolCalls []ExtractionToolCall `json:"tool_calls,omitempty"`
}
ExtractionMessage is the provider-neutral representation of one message passed to a background candidate extractor. It intentionally contains only the frozen compression slice; it is not a session message and must never be written back to a Turn.
type ExtractionToolCall ¶
type LLMCandidateExtractor ¶
type LLMCandidateExtractor struct {
// contains filtered or unexported fields
}
LLMCandidateExtractor is an opt-in extractor. It uses the existing text completion abstraction, while CandidatePipeline keeps its call off the active Turn path and bounds the source sent to the model.
func NewLLMCandidateExtractor ¶
func NewLLMCandidateExtractor(client llm.Client, maxCandidates, maxInputChars int) *LLMCandidateExtractor
func (*LLMCandidateExtractor) Extract ¶
func (e *LLMCandidateExtractor) Extract(ctx context.Context, input ExtractionInput) ([]Candidate, error)
func (*LLMCandidateExtractor) ExtractWithUsage ¶
func (e *LLMCandidateExtractor) ExtractWithUsage(ctx context.Context, input ExtractionInput) ([]Candidate, *llm.Usage, error)
ExtractWithUsage is the usage-aware form used by maintenance accounting. Older llm.Client implementations continue to work; their usage is nil.
type LocalService ¶
type LocalService struct {
// contains filtered or unexported fields
}
LocalService owns the Agent and global stores for one runtime. The selected scope is mutable at a control-plane boundary, while every Recall call still returns a complete immutable Snapshot for its Turn.
func NewLocalService ¶
func NewLocalService(agent, global *Store, scope Scope) *LocalService
func OpenLocalService ¶
func OpenLocalService(agentPath, globalPath string, scope Scope, identity ...string) (*LocalService, error)
func (*LocalService) AgentID ¶
func (s *LocalService) AgentID() string
func (*LocalService) ApplyMaintenanceOperation ¶
func (s *LocalService) ApplyMaintenanceOperation(ctx context.Context, op MaintenanceOperation, candidates []Candidate, next MaintenanceCursor) ([]WriteResult, error)
ApplyMaintenanceOperation atomically commits the operation record, candidate effects, and cursor. Queue submission alone never advances the cursor.
func (*LocalService) Close ¶
func (s *LocalService) Close() error
func (*LocalService) Consolidate ¶
func (s *LocalService) Consolidate(ctx context.Context, candidates []Candidate) ([]WriteResult, error)
Consolidate serially applies model-inferred candidates. Candidates first enter the database as pending and are promoted only when deterministic conflict checks find no existing contradiction. A contradiction remains a normal pending conflict and therefore still requires the existing typed approval flow; background work never auto-approves it.
func (*LocalService) Forget ¶
func (s *LocalService) Forget(ctx context.Context, scope Scope, id, reason string) (WriteResult, error)
func (*LocalService) GetMaintenanceCursor ¶
func (s *LocalService) GetMaintenanceCursor(ctx context.Context) (MaintenanceCursor, error)
GetMaintenanceCursor returns the durable cursor for this service's scope.
func (*LocalService) GetMaintenanceOperation ¶
func (s *LocalService) GetMaintenanceOperation(ctx context.Context, id string) (MaintenanceOperation, error)
GetMaintenanceOperation reads an operation only through the service's private Agent store. It is intentionally independent of the mutable model scope, so a global scope selection cannot widen recovery access.
func (*LocalService) List ¶
func (s *LocalService) List(ctx context.Context, scope Scope, includeInactive bool) ([]Entry, error)
List returns the persisted projection for settings and diagnostics. It is intentionally separate from Recall so inactive entries can be inspected without ever leaking into model context.
func (*LocalService) Maintain ¶
func (s *LocalService) Maintain(ctx context.Context, scope Scope, coreBudget int) (MaintenanceReport, error)
Maintain enforces the deterministic memory housekeeping policy. It is safe to call from a background consolidator: it only changes memory rows and never touches session history or a live Turn snapshot.
func (*LocalService) Recall ¶
func (s *LocalService) Recall(ctx context.Context, req RecallRequest) (Snapshot, error)
func (*LocalService) Remember ¶
func (s *LocalService) Remember(ctx context.Context, req RememberRequest) (WriteResult, error)
func (*LocalService) ReplaceAll ¶
ReplaceAll is the control-plane write used by the settings API. It deliberately bypasses semantic conflict detection because an explicit settings save is an authoritative replacement of the projection.
func (*LocalService) ResolveConflict ¶
func (s *LocalService) ResolveConflict(ctx context.Context, scope Scope, conflictID string, decision ConflictDecision) (WriteResult, error)
func (*LocalService) Scope ¶
func (s *LocalService) Scope() Scope
Scope reports the scope configured for model-facing operations. It is used only to stamp optional background extraction inputs; it does not grant the extractor access to the other store.
func (*LocalService) Search ¶
func (s *LocalService) Search(ctx context.Context, req SearchRequest) ([]SearchResult, error)
func (*LocalService) SetScope ¶
func (s *LocalService) SetScope(scope Scope)
func (*LocalService) UpdateContent ¶
func (s *LocalService) UpdateContent(ctx context.Context, scope Scope, id, content string) (WriteResult, error)
UpdateContent is the explicit settings-plane edit operation. It keeps the entry identity and revision history while rebuilding the search projection.
type Maintainer ¶
type MaintenanceCursor ¶
type MaintenanceCursor struct {
AgentID string `json:"agent_id"`
Scope Scope `json:"scope"`
Sequence int64 `json:"sequence"`
SourceFingerprint string `json:"source_fingerprint"`
CandidateFingerprint string `json:"candidate_fingerprint"`
Revision int64 `json:"revision"`
UpdatedAt time.Time `json:"updated_at"`
}
type MaintenanceOperation ¶
type MaintenanceOperation struct {
OperationID string `json:"operation_id"`
AgentID string `json:"agent_id"`
Scope Scope `json:"scope"`
SourceFingerprint string `json:"source_fingerprint"`
CandidateFingerprint string `json:"candidate_fingerprint"`
ExpectedCursor int64 `json:"expected_cursor"`
NextCursor int64 `json:"next_cursor"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type MaintenanceReport ¶
type RecallRequest ¶
type RecallRequest struct {
AgentID string
Scope Scope
RootMessageID string
QueryText string
Limit int
TokenBudget int
CoreBudget int
// ContextTokenBudget is the hard budget for the complete rendered
// memory_context, including its framing and metadata. TokenBudget and
// CoreBudget remain the per-tier selection budgets.
ContextTokenBudget int
IncludeCore bool
Now time.Time
}
type RememberRequest ¶
type RememberRequest struct {
Scope Scope
AgentID string
Information string
Kind Kind
Tier Tier
SemanticKey string
Subject string
Predicate string
Value any
Qualifiers map[string]string
Cardinality string
Importance int
Confidence int
Sensitivity string
SourceType string
SourceSession string
SourceMessage string
SourceRef string
ValidFrom *time.Time
ValidTo *time.Time
ExpiresAt *time.Time
}
type SearchRequest ¶
type SearchResult ¶
type Service ¶
type Service interface {
Recall(ctx context.Context, req RecallRequest) (Snapshot, error)
Search(ctx context.Context, req SearchRequest) ([]SearchResult, error)
Get(ctx context.Context, scope Scope, id string, includeInactive bool) (Entry, error)
Remember(ctx context.Context, req RememberRequest) (WriteResult, error)
Forget(ctx context.Context, scope Scope, id, reason string) (WriteResult, error)
ResolveConflict(ctx context.Context, scope Scope, conflictID string, decision ConflictDecision) (WriteResult, error)
SetScope(scope Scope)
}
Service 是 Turn/API 依赖的最小能力集合,由 Workspace SQLite 实现。
type Snapshot ¶
type Snapshot struct {
ID string `json:"id"`
Scope Scope `json:"scope"`
StoreRevision int64 `json:"store_revision"`
RootMessageID string `json:"root_message_id"`
Core []Reference `json:"core,omitempty"`
Recalled []Reference `json:"recalled,omitempty"`
RenderedContent string `json:"rendered_content"`
TokenEstimate int `json:"token_estimate"`
Digest string `json:"digest"`
CreatedAt time.Time `json:"created_at"`
}
Snapshot 是一个 Turn 使用的不可变记忆视图。RenderedContent 需要一起 冻结,避免审批恢复或 Node 重启后依据已变化的数据库重新召回出不同上下文。
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store 是单一 scope 的 Workspace SQLite 权威存储。
func (*Store) GetMaintenanceCursor ¶
func (*Store) GetMaintenanceOperation ¶
type WriteOutcome ¶
type WriteOutcome string
const ( WriteAdded WriteOutcome = "added" WriteDuplicate WriteOutcome = "duplicate" WriteSuperseded WriteOutcome = "superseded" WritePendingConflict WriteOutcome = "pending_conflict" )