feat(session): add SessionStore interface and JSONL backend adapter
Extract a SessionStore interface from the methods the agent loop uses (AddMessage, GetHistory, SetSummary, TruncateHistory, Save, etc.). Both SessionManager and the new JSONLBackend satisfy this interface, allowing the persistence layer to be swapped transparently. JSONLBackend wraps memory.Store and maps its error-returning API to the fire-and-forget contract that the agent loop expects — write errors are logged, reads return empty defaults on failure. Save() triggers compaction to reclaim space after logical truncation. Part of #1169
This commit is contained in:
parent
46201fb679
commit
1680e98414
2 changed files with 102 additions and 0 deletions
84
pkg/session/jsonl_backend.go
Normal file
84
pkg/session/jsonl_backend.go
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/sipeed/picoclaw/pkg/memory"
|
||||
"github.com/sipeed/picoclaw/pkg/providers"
|
||||
)
|
||||
|
||||
// JSONLBackend adapts a memory.Store into the SessionStore interface.
|
||||
// Write errors are logged rather than returned, matching the fire-and-forget
|
||||
// contract of SessionManager that the agent loop relies on.
|
||||
type JSONLBackend struct {
|
||||
store memory.Store
|
||||
}
|
||||
|
||||
// NewJSONLBackend wraps a memory.Store for use as a SessionStore.
|
||||
func NewJSONLBackend(store memory.Store) *JSONLBackend {
|
||||
return &JSONLBackend{store: store}
|
||||
}
|
||||
|
||||
func (b *JSONLBackend) AddMessage(sessionKey, role, content string) {
|
||||
if err := b.store.AddMessage(context.Background(), sessionKey, role, content); err != nil {
|
||||
log.Printf("session: add message: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *JSONLBackend) AddFullMessage(sessionKey string, msg providers.Message) {
|
||||
if err := b.store.AddFullMessage(context.Background(), sessionKey, msg); err != nil {
|
||||
log.Printf("session: add full message: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *JSONLBackend) GetHistory(key string) []providers.Message {
|
||||
msgs, err := b.store.GetHistory(context.Background(), key)
|
||||
if err != nil {
|
||||
log.Printf("session: get history: %v", err)
|
||||
return []providers.Message{}
|
||||
}
|
||||
return msgs
|
||||
}
|
||||
|
||||
func (b *JSONLBackend) GetSummary(key string) string {
|
||||
summary, err := b.store.GetSummary(context.Background(), key)
|
||||
if err != nil {
|
||||
log.Printf("session: get summary: %v", err)
|
||||
return ""
|
||||
}
|
||||
return summary
|
||||
}
|
||||
|
||||
func (b *JSONLBackend) SetSummary(key, summary string) {
|
||||
if err := b.store.SetSummary(context.Background(), key, summary); err != nil {
|
||||
log.Printf("session: set summary: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *JSONLBackend) SetHistory(key string, history []providers.Message) {
|
||||
if err := b.store.SetHistory(context.Background(), key, history); err != nil {
|
||||
log.Printf("session: set history: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *JSONLBackend) TruncateHistory(key string, keepLast int) {
|
||||
if err := b.store.TruncateHistory(context.Background(), key, keepLast); err != nil {
|
||||
log.Printf("session: truncate history: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Save persists session state. Since the JSONL store fsyncs every write
|
||||
// immediately, the data is already durable. Save runs compaction to reclaim
|
||||
// space from logically truncated messages (no-op when there are none).
|
||||
func (b *JSONLBackend) Save(key string) error {
|
||||
if err := b.store.Compact(context.Background(), key); err != nil {
|
||||
log.Printf("session: compact %s: %v", key, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close releases resources held by the underlying store.
|
||||
func (b *JSONLBackend) Close() error {
|
||||
return b.store.Close()
|
||||
}
|
||||
18
pkg/session/session_store.go
Normal file
18
pkg/session/session_store.go
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package session
|
||||
|
||||
import "github.com/sipeed/picoclaw/pkg/providers"
|
||||
|
||||
// SessionStore defines the persistence operations used by the agent loop.
|
||||
// Both SessionManager (legacy JSON backend) and JSONLBackend satisfy this
|
||||
// interface, allowing the storage layer to be swapped without touching the
|
||||
// agent loop code.
|
||||
type SessionStore interface {
|
||||
AddMessage(sessionKey, role, content string)
|
||||
AddFullMessage(sessionKey string, msg providers.Message)
|
||||
GetHistory(key string) []providers.Message
|
||||
GetSummary(key string) string
|
||||
SetSummary(key, summary string)
|
||||
SetHistory(key string, history []providers.Message)
|
||||
TruncateHistory(key string, keepLast int)
|
||||
Save(key string) error
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue