//! Repository traits — pure abstraction boundaries for persistence. //! //! Each trait defines load / save / query operations that infrastructure //! adapters implement. The domain and application layers depend **only** //! on these traits, never on concrete persistence implementations. //! //! ## Traits //! - `SettingsRepository` — load/save `Settings` from/to a base directory //! - `AppConfigRepository` — load/save `AppConfig` from/to a base directory //! - `ConversationRepository` — load/save `Conversation` from/to a session directory //! - `MemoryRepository` — list/load/save/delete `Memory` entries //! - `RewindBlobRepository` — store/retrieve/list binary blobs per session //! - `EditLogRepository` — open/append/query edit log entries per session //! //! ## Dependency Inversion //! Application services accept these traits as generic type parameters, //! allowing the composition root to inject concrete implementations //! (file-based, SQLite-backed, etc.) without changing business logic. use std::path::Path; use super::app_config::AppConfig; use super::conversation::Conversation; use super::edit_log::{EditLog, EditLogEntry}; use super::error::RepositoryError; use super::memory::Memory; use super::settings::Settings; /// Persistence contract for `Settings` (application settings model). /// /// Implementors provide the actual I/O logic (e.g. file-based JSON storage). pub trait SettingsRepository { /// Load `Settings` from the given base directory. fn load(&self, base_dir: &Path) -> Result; /// Persist `Settings` to the given base directory. fn save(&self, base_dir: &Path, settings: &Settings) -> Result<(), RepositoryError>; } /// Persistence contract for `AppConfig` (provider and model configuration). /// /// Implementors provide the actual I/O logic (e.g. file-based JSON storage). pub trait AppConfigRepository { /// Load `AppConfig` from the given base directory. fn load(&self, base_dir: &Path) -> Result; /// Persist `AppConfig` to the given base directory. fn save(&self, base_dir: &Path, config: &AppConfig) -> Result<(), RepositoryError>; } /// Persistence contract for `Conversation` (session conversation data). /// /// Implementors provide the actual I/O logic (e.g. file-based JSON storage). pub trait ConversationRepository { /// Load a `Conversation` from the given session directory. fn load(&self, session_dir: &Path) -> Result; /// Persist a `Conversation` to the given session directory. fn save(&self, session_dir: &Path, conversation: &Conversation) -> Result<(), RepositoryError>; } /// Persistence contract for `Memory` (long-term agent memory entries). /// /// Implementors provide the actual I/O logic (e.g. per-memory markdown files). pub trait MemoryRepository { /// List all memory slugs (filenames without extension) in the memory directory. fn list(&self, memory_dir: &Path) -> Result, RepositoryError>; /// Load a single `Memory` by name from the memory directory. fn load(&self, memory_dir: &Path, name: &str) -> Result; /// Save (create or overwrite) a `Memory` in the memory directory. fn save(&self, memory_dir: &Path, memory: &Memory) -> Result<(), RepositoryError>; /// Delete a `Memory` by name from the memory directory. fn delete(&self, memory_dir: &Path, name: &str) -> Result<(), RepositoryError>; } /// Persistence contract for rewind-snapshot binary blobs. /// /// Blobs are keyed by an arbitrary caller-supplied key (e.g. a tool-call ID) /// within a session. They capture file snapshots for the "rewind" feature. pub trait RewindBlobRepository { /// Store (or overwrite) a binary blob under `blob_key` for this session. fn store_blob( &self, session_dir: &Path, blob_key: &str, data: &[u8], mime_type: Option<&str>, ) -> Result<(), RepositoryError>; /// Retrieve a blob's raw bytes by key, or `None` if not found. fn retrieve_blob( &self, session_dir: &Path, blob_key: &str, ) -> Result>, RepositoryError>; /// List all blob keys for this session, ordered oldest-first. fn list_blob_keys(&self, session_dir: &Path) -> Result, RepositoryError>; } /// Persistence contract for `EditLog` (append-only file mutation log). /// /// Implementors manage an append-only log of `EditLogEntry` items per session, /// typically persisted to a file for audit and potential undo. pub trait EditLogRepository { /// Open (or initialise) the edit log for a session directory. fn open(&self, session_dir: &Path) -> Result; /// Append one entry to the log and persist immediately (write-through). fn append( &self, session_dir: &Path, log: &mut EditLog, entry: EditLogEntry, ) -> Result<(), RepositoryError>; /// Return a cloned copy of all in-memory entries for inspection. fn entries(&self, log: &EditLog) -> Vec; }