Menyeragamkan format kode sesuai rustfmt (126 file). Sebelumnya lefthook pre-commit 'cargo fmt --check' akan gagal pada commit apa pun.
123 lines
5.0 KiB
Rust
123 lines
5.0 KiB
Rust
//! 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<Settings, RepositoryError>;
|
|
|
|
/// 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<AppConfig, RepositoryError>;
|
|
|
|
/// 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<Conversation, RepositoryError>;
|
|
|
|
/// 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<Vec<String>, RepositoryError>;
|
|
|
|
/// Load a single `Memory` by name from the memory directory.
|
|
fn load(&self, memory_dir: &Path, name: &str) -> Result<Memory, RepositoryError>;
|
|
|
|
/// 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<Option<Vec<u8>>, RepositoryError>;
|
|
|
|
/// List all blob keys for this session, ordered oldest-first.
|
|
fn list_blob_keys(&self, session_dir: &Path) -> Result<Vec<String>, 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<EditLog, RepositoryError>;
|
|
|
|
/// 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<EditLogEntry>;
|
|
}
|