mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
feat(session): persist scope metadata and aliases
This commit is contained in:
@@ -2,6 +2,7 @@ package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
|
||||
"github.com/sipeed/picoclaw/pkg/memory"
|
||||
@@ -15,24 +16,82 @@ type JSONLBackend struct {
|
||||
store memory.Store
|
||||
}
|
||||
|
||||
type metaAwareStore interface {
|
||||
GetSessionMeta(ctx context.Context, sessionKey string) (memory.SessionMeta, error)
|
||||
UpsertSessionMeta(ctx context.Context, sessionKey string, scope json.RawMessage, aliases []string) error
|
||||
ResolveSessionKey(ctx context.Context, sessionKey string) (string, bool, error)
|
||||
}
|
||||
|
||||
// MetadataAwareSessionStore exposes structured session metadata operations.
|
||||
type MetadataAwareSessionStore interface {
|
||||
EnsureSessionMetadata(sessionKey string, scope *SessionScope, aliases []string)
|
||||
ResolveSessionKey(sessionKey string) string
|
||||
}
|
||||
|
||||
// NewJSONLBackend wraps a memory.Store for use as a SessionStore.
|
||||
func NewJSONLBackend(store memory.Store) *JSONLBackend {
|
||||
return &JSONLBackend{store: store}
|
||||
}
|
||||
|
||||
func (b *JSONLBackend) resolveSessionKey(sessionKey string) string {
|
||||
metaStore, ok := b.store.(metaAwareStore)
|
||||
if !ok {
|
||||
return sessionKey
|
||||
}
|
||||
resolved, found, err := metaStore.ResolveSessionKey(context.Background(), sessionKey)
|
||||
if err != nil {
|
||||
log.Printf("session: resolve session key: %v", err)
|
||||
return sessionKey
|
||||
}
|
||||
if found && resolved != "" {
|
||||
return resolved
|
||||
}
|
||||
return sessionKey
|
||||
}
|
||||
|
||||
// ResolveSessionKey maps aliases onto their canonical session key when the
|
||||
// underlying store supports structured metadata. Unknown aliases fall back to
|
||||
// the original input so existing callers remain compatible.
|
||||
func (b *JSONLBackend) ResolveSessionKey(sessionKey string) string {
|
||||
return b.resolveSessionKey(sessionKey)
|
||||
}
|
||||
|
||||
// EnsureSessionMetadata persists scope and alias metadata for a session.
|
||||
func (b *JSONLBackend) EnsureSessionMetadata(sessionKey string, scope *SessionScope, aliases []string) {
|
||||
metaStore, ok := b.store.(metaAwareStore)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var rawScope json.RawMessage
|
||||
if scope != nil {
|
||||
data, err := json.Marshal(scope)
|
||||
if err != nil {
|
||||
log.Printf("session: encode session scope: %v", err)
|
||||
return
|
||||
}
|
||||
rawScope = data
|
||||
}
|
||||
if err := metaStore.UpsertSessionMeta(context.Background(), sessionKey, rawScope, aliases); err != nil {
|
||||
log.Printf("session: upsert session metadata: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *JSONLBackend) AddMessage(sessionKey, role, content string) {
|
||||
sessionKey = b.resolveSessionKey(sessionKey)
|
||||
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) {
|
||||
sessionKey = b.resolveSessionKey(sessionKey)
|
||||
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 {
|
||||
key = b.resolveSessionKey(key)
|
||||
msgs, err := b.store.GetHistory(context.Background(), key)
|
||||
if err != nil {
|
||||
log.Printf("session: get history: %v", err)
|
||||
@@ -42,6 +101,7 @@ func (b *JSONLBackend) GetHistory(key string) []providers.Message {
|
||||
}
|
||||
|
||||
func (b *JSONLBackend) GetSummary(key string) string {
|
||||
key = b.resolveSessionKey(key)
|
||||
summary, err := b.store.GetSummary(context.Background(), key)
|
||||
if err != nil {
|
||||
log.Printf("session: get summary: %v", err)
|
||||
@@ -51,18 +111,21 @@ func (b *JSONLBackend) GetSummary(key string) string {
|
||||
}
|
||||
|
||||
func (b *JSONLBackend) SetSummary(key, summary string) {
|
||||
key = b.resolveSessionKey(key)
|
||||
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) {
|
||||
key = b.resolveSessionKey(key)
|
||||
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) {
|
||||
key = b.resolveSessionKey(key)
|
||||
if err := b.store.TruncateHistory(context.Background(), key, keepLast); err != nil {
|
||||
log.Printf("session: truncate history: %v", err)
|
||||
}
|
||||
@@ -72,6 +135,7 @@ func (b *JSONLBackend) TruncateHistory(key string, keepLast int) {
|
||||
// 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 {
|
||||
key = b.resolveSessionKey(key)
|
||||
return b.store.Compact(context.Background(), key)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user