open-standards/eoc/eoc-rs/crates/eoc-memory/src/memgpt.rs
Transaction Science 68b8a2dbee ingest wave F: 3 crates · op-crypto-extra + smart-byte-acdc + eoc-memory
OpenPay (1 crate, 3751 LOC, 83 tests)
  op-crypto-extra      Extended crypto rails. Stablecoin catalog (USDC, USDT,
                       PYUSD, DAI, RLUSD, EURC, FDUSD — 26 deployments). L2
                       catalog (12 chains incl. Optimism, Arbitrum, Base,
                       zkSync Era, Polygon zkEVM, Linea, Scroll, Starknet).
                       CCTP v2 BurnMessage encode/decode + domain ids +
                       attestation. ERC-4337 UserOperation v0.7 +
                       PackedUserOperation. EIP-7702 set-EOA-code with RLP
                       signing preimage. Uniswap Permit2 single + batch
                       transfer EIP-712 hashes. EIP-2612 ERC-20 permit.
                       BOLT-11 bech32 invoices + LNURL decode. Bitcoin
                       PSBT v2 (BIP-370). Atomic-swap HTLC. Solana SPL /
                       Aleo / Aztec confidential-transfer sketches.

Smart Byte (1 crate, 2304 LOC, 30 tests)
  smart-byte-acdc      Authentic Chained Data Containers (KERI ecosystem).
                       Acdc + AcdcBuilder (targeted + untargeted) with SAID
                       derivation. JSON Schema 2020-12 validator with
                       oneOf partial-disclosure. TEL (RIP/VRT/ISS/REV)
                       with hash-chained verification. IPEX (apply/offer/
                       agree/grant/admit/spurn) chained by SAID. Edge
                       records (I2I/NI2I/DI2I) + EdgeGraph BFS traversal
                       with cycle detection. Selective disclosure with
                       full/none/subset plans + compact packing.
                       CredentialRegistry trait + InMemoryRegistry over
                       TEL. Composes with smart-byte-core + smart-byte-keri-witness.

EOC (1 crate, 1764 LOC, 16 tests)
  eoc-memory           Long-term memory primitives. Memory trait + MemoryKind +
                       EpisodeId. Episodic event log with TimeIndex range
                       queries. RDF-style Triple store with S/P/O indices.
                       Bounded attention-budget Scratchpad with
                       salience-weighted eviction. Rolling SummaryBuffer +
                       FIFO SlidingWindow. Dream-cycle consolidate()
                       (episodic → semantic). Ebbinghaus forgetting curve
                       with reinforcement. Retriever blending cosine
                       similarity + recency + saturating frequency.
                       MemGpt three-tier shape (Main/Recall/Archival).

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-24 17:28:24 -04:00

119 lines
3.5 KiB
Rust

//! MemGPT-style hierarchical memory.
//!
//! Packer et al. 2023 ("MemGPT: Towards LLMs as Operating Systems")
//! split agent memory into three tiers:
//!
//! 1. **Main context** — always-resident; small, hot, in-prompt.
//! 2. **Recall** — recent overflow; paged in by reference.
//! 3. **Archival** — cold, large, retrievable by query.
//!
//! This module ties together [`Scratchpad`], [`SlidingWindow`] and
//! [`EpisodicLog`] into that three-tier shape.
use serde::{Deserialize, Serialize};
use crate::episodic::{Episode, EpisodicLog};
use crate::error::MemoryResult;
use crate::memory::EpisodeId;
use crate::window::{SlidingWindow, Turn};
use crate::working::Scratchpad;
/// MemGPT tier discriminator.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum Tier {
/// In-prompt working set.
Main,
/// Recent overflow.
Recall,
/// Cold long-term store.
Archival,
}
/// Configuration knobs for a [`MemGpt`] instance.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MemGptConfig {
/// Token budget for the main context scratchpad.
pub main_tokens: u32,
/// Turn capacity of the recall sliding window.
pub recall_turns: usize,
}
impl Default for MemGptConfig {
fn default() -> Self {
Self {
main_tokens: 2048,
recall_turns: 32,
}
}
}
/// Three-tier hierarchical memory bundle.
pub struct MemGpt {
/// Main-context scratchpad.
pub main: Scratchpad,
/// Recall sliding window.
pub recall: SlidingWindow,
/// Archival episodic log.
pub archival: EpisodicLog,
}
impl MemGpt {
/// Build a new MemGpt with the supplied config.
pub fn new(cfg: MemGptConfig) -> MemoryResult<Self> {
Ok(Self {
main: Scratchpad::new(cfg.main_tokens)?,
recall: SlidingWindow::new(cfg.recall_turns)?,
archival: EpisodicLog::new(),
})
}
/// Record a fresh conversation turn:
/// * `recall` gains the turn (oldest evicted on overflow).
/// * The evicted-out turn (if any) is appended to `archival`.
pub fn observe(&mut self, turn: Turn) -> MemoryResult<Option<EpisodeId>> {
let actor = turn.speaker.clone();
let text = turn.text.clone();
let ts = turn.timestamp_ms;
let evicted = self.recall.push(turn);
if let Some(old) = evicted {
let ep = Episode::new(old.timestamp_ms, old.speaker, old.text);
let id = self.archival.append(ep)?;
// The just-pushed turn metadata is also retained for the
// caller to inspect.
let _ = (actor, text, ts);
return Ok(Some(id));
}
Ok(None)
}
/// Manually promote a turn into the archival log (e.g. when the
/// agent calls `archive`).
pub fn archive(
&mut self,
speaker: impl Into<String>,
text: impl Into<String>,
timestamp_ms: u64,
) -> MemoryResult<EpisodeId> {
self.archival
.append(Episode::new(timestamp_ms, speaker, text))
}
/// Which tier currently holds an episode id, if any.
#[must_use]
pub fn locate(&self, id: &EpisodeId) -> Option<Tier> {
if self.archival.get(id).is_some() {
return Some(Tier::Archival);
}
None
}
/// Lengths of each tier, useful for instrumentation.
#[must_use]
pub fn sizes(&self) -> (usize, usize, usize) {
(
self.main.slots().len(),
self.recall.turns().len(),
self.archival.all().len(),
)
}
}