memory

package
v0.0.0-...-3309b9d Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: MIT Imports: 3 Imported by: 0

README

memory — Conversation history persistence

memory defines the core Memory and Conversation interfaces for persisting and retrieving LLM conversation histories, plus marker utilities for metadata annotation (summary, incomplete, ephemeral).

Interfaces

type Memory interface {
    GetConversation(userId, id string, createIfNotExist bool) (Conversation, error)
    ListConversations(userId string) ([]string, error)
    DeleteConversation(userId, id string) error
}

type Conversation interface {
    Append(msg *schema.Message) error
    GetFullMessages() []*schema.Message
    GetMessages(lastSummaryIdx int) []*schema.Message
    AppendSummary(summary *schema.Message) error
    LastSummaryIndex() int
    GetWindow(budget int) ([]*schema.Message, error)
    CountTokens() int
    Load() error
    Save() error
}

Markers

Messages can carry metadata markers via their Extra map:

  • SummaryMarkerKey — marks a message as a conversation summary.
  • IncompleteMarkerKey — marks a message as incomplete (e.g. interrupted streaming).
  • EphemeralMarkerKey — marks a message that should not be persisted.

Helper functions: IsSummary, NewSummaryMessage, MarkIncomplete, IsIncomplete, NewEphemeralMessage, IsEphemeral.

Sub-packages

file — File-based JSONL implementation

Implements Memory/Conversation backed by JSONL files. Supports token-budgeted windowing with binary-search trimming and per-file locking.

session — Turn lifecycle manager

Provides the cross-request lifecycle on top of any Memory store: per-session locking, turn lifecycle (BeginTurn → Condense → Window → CommitAssistant/Discard), and optional summarization-based condensation with configurable thresholds.

runner — ADK Runner bridge

Bridges an ADK Runner.Run to the session turn lifecycle: splits the agent event stream into client streaming and persistence copies, with incomplete/ephemeral message handling and no-dangling-user guarantee.

Usage

import (
    "github.com/webcenter-fr/eino-ext/components/memory"
    "github.com/webcenter-fr/eino-ext/components/memory/file"
    "github.com/webcenter-fr/eino-ext/components/memory/session"
)

mem, _ := file.NewFileMemory(file.FileMemoryConfig{
    Dir: "/var/eino/conversations",
})

sm, _ := session.NewSessionManager(session.Config{
    Memory: mem,
})

turn, _ := sm.BeginTurn("user-123", "conv-456", userMsg)
defer turn.Discard() // rollback on error

window, _ := turn.Window(4000)
turn.CommitAssistant(assistantMsg)

Documentation

Index

Constants

View Source
const EphemeralMarkerKey = "__eino_ext_memory_ephemeral"

EphemeralMarkerKey is the key used in schema.Message.Extra to mark a message as ephemeral: it is streamed to the client but MUST NOT be persisted to the conversation history (e.g. a transient error notice).

View Source
const IncompleteMarkerKey = "__eino_ext_memory_incomplete"

IncompleteMarkerKey is the key used in schema.Message.Extra to mark an assistant message as incomplete (the generation was interrupted, e.g. by an iterator error or a truncated stream). It lets downstream consumers know the persisted answer may be partial.

View Source
const SummaryMarkerKey = "__eino_ext_memory_summary"

SummaryMarkerKey is the key used in schema.Message.Extra to mark a message as a summary.

Variables

View Source
var DefaultTokenCounter = counter.DefaultTokenCounter

Functions

func HasBoolMarker

func HasBoolMarker(msg *schema.Message, key string) bool

HasBoolMarker returns true if msg carries a boolean Extra marker set to true under the given key. It is nil-safe for both the message and its Extra map.

func IsEphemeral

func IsEphemeral(msg *schema.Message) bool

IsEphemeral returns true if msg is marked as ephemeral.

func IsIncomplete

func IsIncomplete(msg *schema.Message) bool

IsIncomplete returns true if msg is marked as incomplete.

func IsSummary

func IsSummary(msg *schema.Message) bool

IsSummary returns true if the message is a summary message.

func LastSummaryIndex

func LastSummaryIndex(msgs []*schema.Message) int

LastSummaryIndex returns the index of the last summary message in msgs, or -1 when none is present. It is the shared implementation used by every Conversation backend.

func MarkIncomplete

func MarkIncomplete(msg *schema.Message)

MarkIncomplete marks msg as incomplete. It creates the Extra map when nil.

func NewEphemeralMessage

func NewEphemeralMessage(role schema.RoleType, content string) *schema.Message

NewEphemeralMessage creates a message marked as ephemeral: it is intended to be streamed to the client but never persisted to the conversation history.

func NewSummaryMessage

func NewSummaryMessage(content string) *schema.Message

NewSummaryMessage creates a new Assistant message marked as a summary.

func SelectWindow

func SelectWindow(msgs []*schema.Message, count TokenCounter, budget, maxWindowTokens int) []*schema.Message

SelectWindow returns [last summary + following messages] from msgs, bounded by a token budget. When budget <= 0, maxWindowTokens is used; when that is also 0, no token cap is applied. Trimming uses binary search (O(log N) calls to count) and always preserves the leading summary (when present) and the last message.

This is the shared windowing logic behind every Conversation backend's GetWindow implementation.

func SetBoolMarker

func SetBoolMarker(msg *schema.Message, key string)

SetBoolMarker sets a boolean Extra marker to true under the given key, allocating the Extra map when needed. It is a no-op for a nil message.

Types

type Conversation

type Conversation interface {
	// Append adds a message to the conversation.
	Append(msg *schema.Message)

	// GetFullMessages returns all messages in the conversation.
	GetFullMessages() []*schema.Message

	// GetMessages returns the messages in the conversation. The number of messages returned is limited by the max window size of the conversation.
	GetMessages() []*schema.Message

	// Load loads the conversation from the storage.
	Load() error

	// Save saves the conversation to the storage.
	Save(msg *schema.Message) error

	// AppendSummary adds a summary-marked message to the conversation (non-destructive).
	AppendSummary(summary *schema.Message)

	// GetWindow returns [last summary + following messages], bounded by a token budget.
	// If budget <= 0, only applies the last-summary trimming without a token cap.
	GetWindow(budget int) []*schema.Message

	// CountTokens counts the tokens in the current window (via the injected TokenCounter).
	CountTokens() int

	// LastSummaryIndex returns the index of the last summary message, or -1 if none.
	LastSummaryIndex() int

	// GetActivities returns all stored activity events.
	GetActivities() []json.RawMessage

	// SetActivities replaces all stored activity events (batch write after run).
	SetActivities(raw []json.RawMessage)

	// GetUpdatedAt returns the RFC3339 timestamp of the last update, or "" if
	// the backend does not track this information.
	GetUpdatedAt() string
}

type Memory

type Memory interface {
	// GetConversation returns the conversation with the given id. If createIfNotExist is true and the conversation does not exist, it creates a new conversation.
	GetConversation(userId string, id string, createIfNotExist bool) (Conversation, error)

	// ListConversations returns a list of conversation ids for the given user.
	ListConversations(userId string) ([]string, error)

	// DeleteConversation deletes the conversation with the given id.
	DeleteConversation(userId string, id string) error
}

type TokenCounter

type TokenCounter = counter.TokenCounter

Directories

Path Synopsis
examples
contextopt_persistent command
Command contextopt_persistent demonstrates how to combine the cross-request session condenser (components/memory/session) with the intra-run context optimizer (components/middleware/contextopt) WITHOUT paying the LLM summarization cost twice.
Command contextopt_persistent demonstrates how to combine the cross-request session condenser (components/memory/session) with the intra-run context optimizer (components/middleware/contextopt) WITHOUT paying the LLM summarization cost twice.
Package runner bridges an eino adk.Runner run to the cross-request session lifecycle (session.Turn) so that any eino project gets streaming + history persistence out of the box, without re-implementing the glue per project.
Package runner bridges an eino adk.Runner run to the cross-request session lifecycle (session.Turn) so that any eino project gets streaming + history persistence out of the box, without re-implementing the glue per project.
Package session provides the generic, cross-request lifecycle for persisting a conversation history on top of a memory.Memory store.
Package session provides the generic, cross-request lifecycle for persisting a conversation history on top of a memory.Memory store.

Jump to

Keyboard shortcuts

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