记忆

Cross-session Memory Sharing

跨会话记忆共享 - 多会话间的记忆共享和访问控制

跨会话记忆共享 (Cross-session Memory Sharing)

概述

Cross-session Memory Sharing 提供了一个强大的会话间记忆共享系统,支持私有、共享和全局三种作用域,以及细粒度的访问控制。

核心功能

  • 多作用域支持 - Private(私有)、Shared(共享)、Global(全局)
  • 访问控制 - None、Read、Write、FullControl 四级权限
  • 所有者模型 - 基于所有者的权限管理
  • 会话隔离 - 自动的会话级记忆隔离
  • 过期清理 - 自动清理过期记忆

快速开始

1. 创建会话记忆管理器

package main

import (
    "context"
    "github.com/astercloud/aster/pkg/memory"
)

func main() {
    // 创建会话记忆管理器
    config := memory.DefaultSessionManagerConfig()
    manager := memory.NewSessionMemoryManager(config)

    // 添加私有记忆
    memID, err := manager.AddMemory(
        context.Background(),
        "session-1",
        "User prefers dark mode",
        map[string]interface{}{"category": "preference"},
        memory.ScopePrivate,
    )

    if err != nil {
        panic(err)
    }
}

2. 共享记忆给其他会话

// session-1 共享记忆给 session-2
err := manager.ShareMemory(
    ctx,
    memID,
    "session-1",  // from (所有者)
    "session-2",  // to (目标会话)
    memory.AccessRead, // 访问级别
)

if err != nil {
    panic(err)
}

// session-2 现在可以读取这个记忆
mem, err := manager.GetMemory(ctx, memID, "session-2")
if err == nil {
    fmt.Printf("Shared memory: %s\n", mem.Content)
}

3. 使用全局记忆

// 创建全局记忆(所有会话可见)
globalMemID, _ := manager.AddMemory(
    ctx,
    "session-1",
    "System maintenance scheduled for tonight",
    nil,
    memory.ScopeGlobal,
)

// 任何会话都可以读取全局记忆
mem, _ := manager.GetMemory(ctx, globalMemID, "session-100")
fmt.Printf("Global announcement: %s\n", mem.Content)

记忆作用域

ScopePrivate - 私有记忆

// 只有创建者会话可以访问
memID, _ := manager.AddMemory(
    ctx,
    "session-1",
    "My secret note",
    nil,
    memory.ScopePrivate,
)

// session-1 可以访问
mem, _ := manager.GetMemory(ctx, memID, "session-1") // ✅

// session-2 无法访问
_, err := manager.GetMemory(ctx, memID, "session-2") // ❌ Access denied

ScopeShared - 共享记忆

// 创建私有记忆
memID, _ := manager.AddMemory(
    ctx,
    "session-1",
    "Project plan",
    nil,
    memory.ScopePrivate,
)

// 共享给特定会话
manager.ShareMemory(ctx, memID, "session-1", "session-2", memory.AccessRead)
manager.ShareMemory(ctx, memID, "session-1", "session-3", memory.AccessWrite)

// session-2 可以读
mem, _ := manager.GetMemory(ctx, memID, "session-2") // ✅

// session-3 可以读写
manager.UpdateMemory(ctx, memID, "session-3", "Updated plan", nil) // ✅

// session-4 无法访问
_, err := manager.GetMemory(ctx, memID, "session-4") // ❌ Access denied

ScopeGlobal - 全局记忆

// 所有会话可以读取全局记忆
globalMemID, _ := manager.AddMemory(
    ctx,
    "admin-session",
    "Company-wide announcement",
    nil,
    memory.ScopeGlobal,
)

// 任何会话都可以读
mem, _ := manager.GetMemory(ctx, globalMemID, "random-session-123") // ✅

// 但只有所有者可以修改
manager.UpdateMemory(ctx, globalMemID, "random-session", "Try to modify", nil) // ❌
manager.UpdateMemory(ctx, globalMemID, "admin-session", "Modified", nil) // ✅

访问级别

AccessNone - 无权限

默认状态,无法访问记忆。

AccessRead - 只读权限

manager.ShareMemory(ctx, memID, "session-1", "session-2", memory.AccessRead)

// session-2 可以读
mem, _ := manager.GetMemory(ctx, memID, "session-2") // ✅

// 但不能写
err := manager.UpdateMemory(ctx, memID, "session-2", "Try to update", nil) // ❌

AccessWrite - 读写权限

manager.ShareMemory(ctx, memID, "session-1", "session-2", memory.AccessWrite)

// session-2 可以读写
mem, _ := manager.GetMemory(ctx, memID, "session-2") // ✅
manager.UpdateMemory(ctx, memID, "session-2", "Updated", nil) // ✅

// 但不能删除(只有所有者可以)
err := manager.DeleteMemory(ctx, memID, "session-2") // ❌

AccessFullControl - 完全控制

manager.ShareMemory(ctx, memID, "session-1", "session-2", memory.AccessFullControl)

// session-2 可以读写
mem, _ := manager.GetMemory(ctx, memID, "session-2") // ✅
manager.UpdateMemory(ctx, memID, "session-2", "Updated", nil) // ✅

// 但仍然不能删除(删除是所有者专属权限)
err := manager.DeleteMemory(ctx, memID, "session-2") // ❌ Only owner can delete

核心操作

添加记忆

memID, err := manager.AddMemory(
    ctx,
    "session-id",
    "Memory content",
    map[string]interface{}{
        "tag": "important",
        "priority": 5,
    },
    memory.ScopePrivate,
)

共享记忆

// 所有者共享记忆给其他会话
err := manager.ShareMemory(
    ctx,
    memID,
    "owner-session",
    "target-session",
    memory.AccessRead,
)

// 检查共享数量限制(默认 100)
config := memory.DefaultSessionManagerConfig()
config.MaxSharedSessions = 10 // 最多共享给 10 个会话

撤销访问

// 所有者撤销共享
err := manager.RevokeAccess(
    ctx,
    memID,
    "owner-session",
    "target-session",
)

更新记忆

// 需要 Write 或 FullControl 权限
err := manager.UpdateMemory(
    ctx,
    memID,
    "session-id",
    "Updated content",
    map[string]interface{}{"updated": true},
)

删除记忆

// 只有所有者可以删除
err := manager.DeleteMemory(ctx, memID, "owner-session") // ✅
err := manager.DeleteMemory(ctx, memID, "other-session") // ❌

列出记忆

// 列出会话可访问的所有记忆
memories, err := manager.ListSessionMemories(ctx, "session-1", "")

// 按作用域过滤
privateMemories, _ := manager.ListSessionMemories(ctx, "session-1", memory.ScopePrivate)
globalMemories, _ := manager.ListSessionMemories(ctx, "session-1", memory.ScopeGlobal)

配置参考

SessionManagerConfig

config := memory.SessionManagerConfig{
    // 默认作用域
    DefaultScope: memory.ScopePrivate,

    // 是否允许跨会话共享
    EnableSharing: true,

    // 是否允许全局记忆
    EnableGlobal: true,

    // 记忆过期时间
    MemoryTTL: 7 * 24 * time.Hour, // 7 天

    // 最大共享数量
    MaxSharedSessions: 100,
}

manager := memory.NewSessionMemoryManager(config)

高级用法

1. 带溯源的共享记忆

// 添加记忆时自动创建溯源信息
memID, _ := manager.AddMemory(
    ctx,
    "session-1",
    "User feedback: UI is confusing",
    map[string]interface{}{"source": "feedback"},
    memory.ScopePrivate,
)

// 获取记忆时查看溯源
mem, _ := manager.GetMemory(ctx, memID, "session-1")
fmt.Printf("Source: %s\n", mem.Provenance.Source)
fmt.Printf("Confidence: %.2f\n", mem.Provenance.Confidence)

2. 统计信息

stats := manager.GetStats()

fmt.Printf("总记忆数: %d\n", stats.TotalMemories)
fmt.Printf("总会话数: %d\n", stats.TotalSessions)
fmt.Printf("全局记忆数: %d\n", stats.GlobalMemories)
fmt.Printf("私有记忆: %d\n", stats.ScopeDistribution[memory.ScopePrivate])
fmt.Printf("全局记忆: %d\n", stats.ScopeDistribution[memory.ScopeGlobal])

3. 过期清理

// 手动触发清理
removed := manager.CleanupExpired(ctx)
fmt.Printf("清理了 %d 个过期记忆\n", removed)

// 定期自动清理
ticker := time.NewTicker(24 * time.Hour)
go func() {
    for range ticker.C {
        removed := manager.CleanupExpired(ctx)
        log.Printf("清理了 %d 个过期记忆", removed)
    }
}()

4. 批量操作

// 批量添加记忆
memories := []struct {
    content string
    scope   memory.MemoryScope
}{
    {"Memory 1", memory.ScopePrivate},
    {"Memory 2", memory.ScopeGlobal},
    {"Memory 3", memory.ScopePrivate},
}

memIDs := []string{}
for _, mem := range memories {
    id, _ := manager.AddMemory(ctx, "session-1", mem.content, nil, mem.scope)
    memIDs = append(memIDs, id)
}

// 批量共享
for _, memID := range memIDs {
    manager.ShareMemory(ctx, memID, "session-1", "session-2", memory.AccessRead)
}

最佳实践

1. 选择合适的作用域

// ✅ 用户特定数据 → Private
manager.AddMemory(ctx, sessionID, "User's API key", nil, memory.ScopePrivate)

// ✅ 团队协作数据 → Shared(通过 ShareMemory 控制)
memID, _ := manager.AddMemory(ctx, sessionID, "Team notes", nil, memory.ScopePrivate)
manager.ShareMemory(ctx, memID, sessionID, "team-member-1", memory.AccessWrite)

// ✅ 系统公告 → Global
manager.AddMemory(ctx, "admin", "System maintenance tonight", nil, memory.ScopeGlobal)

2. 最小权限原则

// ✅ 只需要读 → AccessRead
manager.ShareMemory(ctx, memID, owner, viewer, memory.AccessRead)

// ✅ 需要协作编辑 → AccessWrite
manager.ShareMemory(ctx, memID, owner, collaborator, memory.AccessWrite)

// ❌ 避免滥用 FullControl
// manager.ShareMemory(ctx, memID, owner, user, memory.AccessFullControl)

3. 定期清理

// 设置合理的 TTL
config := memory.DefaultSessionManagerConfig()
config.MemoryTTL = 30 * 24 * time.Hour // 30 天

// 定期清理
ticker := time.NewTicker(24 * time.Hour)
go func() {
    for range ticker.C {
        manager.CleanupExpired(ctx)
    }
}()

4. 权限验证

// 在共享前验证所有者
mem, err := manager.GetMemory(ctx, memID, sessionID)
if err != nil {
    return err
}

if mem.OwnerID != sessionID {
    return fmt.Errorf("only owner can share")
}

// 然后执行共享
manager.ShareMemory(ctx, memID, sessionID, targetSession, memory.AccessRead)

使用场景

场景 1:个人助手

// 每个用户有自己的会话
userSession := "user-123"

// 存储用户偏好(私有)
manager.AddMemory(ctx, userSession, "Prefers dark mode", nil, memory.ScopePrivate)
manager.AddMemory(ctx, userSession, "Timezone: UTC+8", nil, memory.ScopePrivate)

场景 2:团队协作

// 团队长创建共享记忆
teamLeadSession := "team-lead-1"
memID, _ := manager.AddMemory(
    ctx,
    teamLeadSession,
    "Project requirements document",
    nil,
    memory.ScopePrivate,
)

// 共享给团队成员
members := []string{"member-1", "member-2", "member-3"}
for _, member := range members {
    manager.ShareMemory(ctx, memID, teamLeadSession, member, memory.AccessRead)
}

// 给协作者写权限
manager.ShareMemory(ctx, memID, teamLeadSession, "co-lead", memory.AccessWrite)

场景 3:系统公告

// 管理员创建全局公告
adminSession := "admin"
manager.AddMemory(
    ctx,
    adminSession,
    "New feature released: Dark mode support",
    map[string]interface{}{
        "type": "announcement",
        "date": time.Now(),
    },
    memory.ScopeGlobal,
)

// 所有用户自动可见

测试

运行跨会话共享测试:

go test ./pkg/memory/... -run TestSession -v

相关文档

参考资源