feat: implement memory management system with SQLite persistence, including conversation windows and episodic facts
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
package memory
|
||||
|
||||
import "context"
|
||||
|
||||
// Store is the interface for persistent memory operations.
|
||||
// Defined in the pure package; implemented by shell/memory.
|
||||
type Store interface {
|
||||
// Facts
|
||||
SaveFact(ctx context.Context, fact Fact) error
|
||||
RecallFacts(ctx context.Context, agentID, subject string, key *string) ([]Fact, error)
|
||||
DeleteFacts(ctx context.Context, agentID, subject string, key *string) error
|
||||
|
||||
// Message history
|
||||
SaveMessage(ctx context.Context, msg HistoryMessage) error
|
||||
LoadMessages(ctx context.Context, agentID, roomID string, limit int) ([]HistoryMessage, error)
|
||||
DeleteMessages(ctx context.Context, agentID string, roomID *string) error
|
||||
|
||||
// Lifecycle
|
||||
Close() error
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Package memory provides pure types for agent memory: conversation windows and episodic facts.
|
||||
package memory
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/enmanuel/agents/pkg/llm"
|
||||
)
|
||||
|
||||
// Fact is a single episodic fact: a key-value pair scoped to a subject.
|
||||
type Fact struct {
|
||||
AgentID string
|
||||
Subject string
|
||||
Key string
|
||||
Value string
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
// HistoryMessage is a persisted conversation message.
|
||||
type HistoryMessage struct {
|
||||
AgentID string
|
||||
RoomID string
|
||||
Role llm.Role
|
||||
Content string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package memory
|
||||
|
||||
import "github.com/enmanuel/agents/pkg/llm"
|
||||
|
||||
// Window is an immutable sliding window of conversation messages for a single room.
|
||||
type Window struct {
|
||||
messages []llm.Message
|
||||
maxSize int
|
||||
}
|
||||
|
||||
// NewWindow creates an empty window with the given capacity.
|
||||
func NewWindow(maxSize int) Window {
|
||||
return Window{maxSize: maxSize}
|
||||
}
|
||||
|
||||
// Append returns a new Window with the message added, dropping the oldest
|
||||
// messages if capacity is exceeded.
|
||||
func (w Window) Append(msg llm.Message) Window {
|
||||
msgs := make([]llm.Message, len(w.messages), len(w.messages)+1)
|
||||
copy(msgs, w.messages)
|
||||
msgs = append(msgs, msg)
|
||||
if len(msgs) > w.maxSize {
|
||||
msgs = msgs[len(msgs)-w.maxSize:]
|
||||
}
|
||||
return Window{messages: msgs, maxSize: w.maxSize}
|
||||
}
|
||||
|
||||
// ToLLMMessages returns a copy of the window contents as []llm.Message.
|
||||
func (w Window) ToLLMMessages() []llm.Message {
|
||||
out := make([]llm.Message, len(w.messages))
|
||||
copy(out, w.messages)
|
||||
return out
|
||||
}
|
||||
|
||||
// Len returns the number of messages in the window.
|
||||
func (w Window) Len() int {
|
||||
return len(w.messages)
|
||||
}
|
||||
|
||||
// Clear returns an empty window with the same capacity.
|
||||
func (w Window) Clear() Window {
|
||||
return NewWindow(w.maxSize)
|
||||
}
|
||||
Reference in New Issue
Block a user