"""Beaver memory 应用服务。 这层不是新的 memory 实现,而是对现有 `MemoryStore + MemorySnapshot` 的应用层包装。 目标只有三个: 1. 把“本轮运行前需要 refresh live state”这件事集中到一个地方 2. 把“给 context builder 的只能是 frozen snapshot”这条规则写死 3. 让 `AgentLoop` 不再直接操作 `MemoryStore` 细节 设计边界: 1. 记忆实际读写逻辑仍然在 `beaver.memory.curated.store.MemoryStore` 2. memory tool 仍然直接写 store 3. 本服务只负责 runtime 接入策略,不负责 CRUD 业务本身 """ from __future__ import annotations from pathlib import Path from beaver.memory.curated.snapshot import MemorySnapshot, capture_memory_snapshot from beaver.memory.curated.store import MemoryStore class MemoryService: """统一封装 runtime 对 curated memory 的访问方式。""" def __init__( self, root: str | Path, *, store: MemoryStore | None = None, ) -> None: self.root = Path(root) self.store = store or MemoryStore(self.root) self._snapshot: MemorySnapshot | None = None def initialize(self) -> None: """启动时加载一次磁盘内容,建立首份 frozen snapshot 基线。""" self.store.load_from_disk() self._snapshot = capture_memory_snapshot(self.store) def reload_for_new_run(self) -> None: """每次新 run 开始前刷新 live state。 这是 Beaver memory policy 的关键点: - 上一次会话中通过 tool 写入的持久记忆,下一次运行应该能看到 - 但同一次 run 中途写入的新记忆,不应反向修改当前 frozen snapshot """ self.store.load_from_disk() self._snapshot = capture_memory_snapshot(self.store) def capture_snapshot_for_run(self) -> MemorySnapshot: """Capture a per-run frozen snapshot without mutating shared runtime state.""" store = MemoryStore(self.root) store.load_from_disk() return capture_memory_snapshot(store) def get_snapshot(self) -> MemorySnapshot: """获取当前 run 应注入 system prompt 的 frozen snapshot。""" if self._snapshot is None: # 兜底场景:如果调用方绕过 initialize/reload,首次读取时仍建立一份快照。 self._snapshot = capture_memory_snapshot(self.store) return self._snapshot def get_store(self) -> MemoryStore: """暴露底层 store 给需要直接调用 CRUD 的工具层。""" return self.store