3.1 KiB
Grid-agent conversation memory
ConversationStore owns bounded conversational context independently of the
grid connection generation. Its key is the immutable avatar UUID plus exactly
one channel kind: public chat or direct IM. Group and conference conversations
are deliberately not representable. Public sessions expire at exactly 30
minutes of monotonic inactivity and direct IM sessions at exactly 24 hours. A
subsequent turn creates a cryptographically random new session ID and receives
none of the expired transcript.
The mutex-protected store assigns one sequence order to concurrent turns. It stores wall-clock timestamps, normalized avatar/agent/tool roles, visible agent responses, bounded tool summaries, and externally meaningful action results. Avatar input and untrusted tool data remain untrusted when compacted. There is no system-message, model-scratchpad, hidden-reasoning, credential, capability URL, or binary-asset input variant. Text is bounded and sensitive URL/token forms are redacted before allocation in the store.
Configured limits lower hard ceilings for active sessions, turns, per-session bytes, aggregate bytes, tool-result count and size, summary bytes, and total snapshot storage. Old records compact deterministically into a smaller factual summary followed by recent context. Session and aggregate pressure evict the least-recently-active key with UUID/channel tie-breaking. Expiry, compaction, eviction, quarantine, and operator deletion publish stable reason codes through a bounded event queue.
list_metadata returns session ID, UUID, channel, timestamps, turn count, and
byte count but never content. Operators can delete or expire an exact key.
context is the separate LLM-facing projection and can read only that key;
untrusted summaries are emitted as explicitly marked user-role data.
Persistence is local and opt-in through conversation.persistence_enabled.
ConversationStore::from_config uses storage_path/conversations; callers
flush at their durability boundary. A flush writes and syncs a new immutable,
versioned generation before an atomic rename, then retains only generations
whose aggregate bytes fit the configured storage ceiling. Linux and other Unix
targets force directory mode 0700 and file mode 0600. Rust standard library
does not expose a portable Windows ACL editor, so Windows emits the explicit
PermissionsNotVerified event and operators must restrict the directory ACL to
the service identity.
Restart recovery validates schema, UUIDs, IDs, unique sequences, timestamps, roles, bounds, and redaction before any record can become LLM context. A truncated, corrupt, oversized, or unsupported generation is quarantined and an older valid generation is tried. If the wall clock moved backwards, recovered age is zero; forward elapsed time is applied to the channel TTL. Neither case can grant policy authority or prevent startup.
Focused gates:
cargo test --locked -p metacrate-grid-agent --lib conversation_tests
cargo test --locked -p metacrate-grid-agent --test conversation_memory
cargo clippy --locked -p metacrate-grid-agent --all-targets -- -D warnings