| 1 | //! CodeWhale memory: a local library, not a second agent loop. |
| 2 | //! |
| 3 | //! Hosts construct [`Access`] from their trusted runtime, never model arguments. |
| 4 | //! Captures are candidates. Only a trusted reviewer can promote them. Search |
| 5 | //! filters scope, status, expiry, and repository freshness before ranking. |
| 6 | //! The synchronous SQLite owner belongs on a blocking worker, not the UI thread. |
| 7 | #![forbid(unsafe_code)] |
| 8 | |
| 9 | pub mod auth; |
| 10 | pub mod context; |
| 11 | pub mod hooks; |
| 12 | pub mod import; |
| 13 | pub mod lens; |
| 14 | pub mod model; |
| 15 | pub mod policy; |
| 16 | pub mod protocol; |
| 17 | pub mod runtime; |
| 18 | pub mod store; |
| 19 | pub mod workspace; |
| 20 | |
| 21 | pub use auth::{Access, Capability}; |
| 22 | pub use context::{ByteCounter, ContextBudget, ContextPacket, TokenCounter, compile_context}; |
| 23 | pub use model::*; |
| 24 | pub use store::{MemoryBackend, Store}; |
| 25 | |
| 26 | #[derive(Debug, thiserror::Error)] |
| 27 | pub enum Error { |
| 28 | #[error("memory access denied")] |
| 29 | Denied, |
| 30 | #[error("memory not found in the authorized scope")] |
| 31 | NotFound, |
| 32 | #[error("revision conflict; reload before writing")] |
| 33 | RevisionConflict, |
| 34 | #[error("an active memory already owns this key")] |
| 35 | KeyConflict, |
| 36 | #[error("request key was already used for different content")] |
| 37 | IdempotencyConflict, |
| 38 | #[error("this exact memory was forgotten; automatic reimport is blocked")] |
| 39 | Forgotten, |
| 40 | #[error("memory is not in a valid state for this operation")] |
| 41 | InvalidState, |
| 42 | #[error("a trusted, content-bound passing validation receipt is required")] |
| 43 | ValidationRequired, |
| 44 | #[error("a parent is not active or has expired")] |
| 45 | InvalidParent, |
| 46 | #[error("possible secret detected; content was not persisted")] |
| 47 | SecretDetected, |
| 48 | #[error("invalid input: {0}")] |
| 49 | Invalid(String), |
| 50 | #[error("unsupported or non-memory database; no migration was attempted")] |
| 51 | DatabaseMismatch, |
| 52 | #[error("memory is disabled")] |
| 53 | Disabled, |
| 54 | #[error("storage error")] |
| 55 | Sql(#[from] rusqlite::Error), |
| 56 | #[error("JSON encoding or decoding error")] |
| 57 | Json(#[from] serde_json::Error), |
| 58 | #[error("filesystem or stream error")] |
| 59 | Io(#[from] std::io::Error), |
| 60 | } |
| 61 | |
| 62 | impl Error { |
| 63 | /// Safe public code: never echoes a SQL statement, a path, or secret input. |
| 64 | pub fn code(&self) -> &'static str { |
| 65 | match self { |
| 66 | Self::Denied => "denied", |
| 67 | Self::NotFound => "not_found", |
| 68 | Self::RevisionConflict => "revision_conflict", |
| 69 | Self::KeyConflict => "key_conflict", |
| 70 | Self::IdempotencyConflict => "idempotency_conflict", |
| 71 | Self::Forgotten => "forgotten", |
| 72 | Self::InvalidState => "invalid_state", |
| 73 | Self::ValidationRequired => "validation_required", |
| 74 | Self::InvalidParent => "invalid_parent", |
| 75 | Self::SecretDetected => "secret_detected", |
| 76 | Self::Invalid(_) => "invalid_input", |
| 77 | Self::DatabaseMismatch => "database_mismatch", |
| 78 | Self::Disabled => "disabled", |
| 79 | Self::Sql(_) => "storage_error", |
| 80 | Self::Json(_) => "json_error", |
| 81 | Self::Io(_) => "io_error", |
| 82 | } |
| 83 | } |
| 84 | } |
| 85 | pub type Result<T> = std::result::Result<T, Error>; |
| 86 |