ares-store 0.9.1

Database and vector store clients for ARES
Documentation
//! Database Clients and Vector Stores
//!
//! This module provides database abstractions for:
//! - **PostgreSQL**: Relational database for conversations, users, etc.
//! - **Vector Stores**: Multi-provider vector database support
//!
//! # Relational Database
//!
//! The [`PostgresClient`] provides async access to PostgreSQL for:
//! - User management (registration, authentication)
//! - Conversation storage and retrieval
//! - Message history
//! - User memory (facts, preferences)
//!
//! # Vector Store Providers
//!
//! The following vector store backends are supported:
//! - `ares-vector` (default) - Pure Rust embedded HNSW vector database
//! - `lancedb` - Serverless, embedded vector database (may have build issues on Windows)
//! - `qdrant` - High-performance vector search engine
//! - `pgvector` - PostgreSQL extension
//! - `chromadb` - Simple embedding database
//! - `pinecone` - Managed cloud service
//!
//! Enable providers via Cargo features:
//! ```toml
//! ares = { version = "*", features = ["ares-vector", "qdrant"] }
//! ```
//!
//! # Example
//!
//! ```ignore
//! use ares::db::{PostgresClient, VectorStore, AresVectorStore};
//!
//! // Relational database
//! let db = PostgresClient::new("postgres://user:pass@localhost:5432/ares").await?;
//! let user = db.get_user_by_id(user_id).await?;
//!
//! // Vector store
//! let vector_store = AresVectorStore::new("./vectors").await?;
//! vector_store.upsert("docs", embeddings, metadata).await?;
//! let results = vector_store.search("docs", query_embedding, 10).await?;
//! ```

#![allow(clippy::too_many_arguments)]
#![allow(clippy::type_complexity)]
#![allow(clippy::redundant_closure)]
#![allow(unused_imports)]
#![allow(clippy::needless_borrows_for_generic_args)]
#![allow(clippy::option_as_ref_deref)]
#![allow(clippy::map_flatten)]
#![allow(clippy::for_kv_map)]

pub mod config;
pub mod billing_config;
pub mod fleet_secrets;
pub use config::{DatabaseConfig, QdrantConfig, default_qdrant_url};
pub use billing_config::{BillingConfig, ModelPricingConfig};
pub use fleet_secrets::{
    decrypt_api_key, encrypt_api_key, last_n_visible, EncryptedPayload, FleetSecrets,
    FleetSecretsError, MasterKey, ProviderOverride,
};

// Vector store abstraction layer
pub mod vectorstore;

// Provider implementations
#[cfg(feature = "ares-vector")]
pub mod ares_vector;
#[cfg(feature = "chromadb")]
pub mod chromadb;
#[cfg(any(feature = "lancedb", feature = "postgres"))]
pub mod lancedb;
#[cfg(any(feature = "pgvector", feature = "postgres"))]
pub mod pgvector;
#[cfg(any(feature = "pinecone", feature = "postgres"))]
pub mod pinecone;
#[cfg(any(feature = "qdrant", feature = "postgres"))]
pub mod qdrant;

// Relational database (requires postgres feature for sqlx)
#[cfg(feature = "postgres")]
/// Agent run tracking (execution history).
pub mod agent_runs;
#[cfg(feature = "postgres")]
/// Reviewer and quality feedback attached to agent runs.
pub mod agent_feedback;
#[cfg(feature = "postgres")]
/// Platform alerts (health, quota, errors).
pub mod alerts;
#[cfg(feature = "postgres")]
/// Admin audit log (mutation tracking).
pub mod audit_log;
#[cfg(feature = "postgres")]
/// PostgreSQL database client implementation.
pub mod postgres;
#[cfg(feature = "postgres")]
/// Per-tenant agent instance management.
pub mod tenant_agents;
#[cfg(feature = "postgres")]
/// Multi-tenant tenant management.
pub mod tenants;
#[cfg(feature = "postgres")]
/// Per-tenant Cordis child contexts (temporal tenancy).
pub mod realms;
#[cfg(feature = "postgres")]
pub use realms::TenantRealms;
/// Database traits and common types shared across providers.
#[cfg(feature = "postgres")]
pub mod traits;
/// Turso/libSQL database client (alternative to PostgreSQL).
#[cfg(feature = "turso")]
pub mod turso;
#[cfg(feature = "postgres")]
/// Agent config version history (Sprint 11).
pub mod agent_versions;
#[cfg(feature = "postgres")]
pub use agent_versions::AgentVersionInput;
#[cfg(feature = "postgres")]
/// Fleet-wide, tenant-agnostic provider API key & config storage.
pub mod fleet_provider_secrets;
#[cfg(feature = "postgres")]
/// Runtime-defined LLM provider configurations.
pub mod runtime_providers;
#[cfg(feature = "postgres")]
/// Per-tenant model tier mapping (abstract tier -> concrete provider/model).
pub mod tenant_model_tiers;
#[cfg(feature = "postgres")]
/// Per-tenant allowlist for tools, models, and RAG sources.
pub mod tenant_allowlist;
#[cfg(feature = "postgres")]
/// Per-tenant LLM token budget tracking.
pub mod token_budgets;
#[cfg(feature = "postgres")]
/// Runtime-defined tools (HTTP, MCP, Script, SQL).
pub mod runtime_tools;
#[cfg(feature = "postgres")]
/// Detailed run history: LLM calls, tool calls, costs, budgets, health metrics.
pub mod run_history;
#[cfg(feature = "postgres")]
/// Custom skills and connector configurations.
pub mod skills;
#[cfg(feature = "postgres")]
/// Agent schedules, event triggers, and pipeline links.
pub mod schedules;
#[cfg(feature = "postgres")]
/// OAuth credential storage for third-party connectors.
pub mod oauth_credentials;
#[cfg(feature = "postgres")]
/// Pure SQL builders and row conversions (testable without a live DB).
pub mod query_builders;

// Re-exports
pub use vectorstore::{CollectionInfo, CollectionStats, VectorStore, VectorStoreProvider};

#[cfg(feature = "ares-vector")]
pub use ares_vector::AresVectorStore;
#[cfg(feature = "lancedb")]
pub use lancedb::LanceDBStore;
#[cfg(feature = "postgres")]
pub use postgres::PostgresClient;
#[cfg(feature = "turso")]
pub use turso::TursoClient;
#[cfg(feature = "qdrant")]
pub use qdrant::QdrantVectorStore;
#[cfg(feature = "postgres")]
pub use tenants::{TenantDb, UsageSummary};

#[cfg(feature = "postgres")]
pub type Store = TenantDb;

mod plugins;
pub use plugins::register_plugins;

/// Cordis Service for postgres availability — runtime check replaces `#[cfg(feature = "postgres")]` in handlers.
///
/// `check()` returns `cfg!(feature = "postgres")` so both `cargo check --no-default-features` and
/// `cargo check --features postgres` compile; handlers branch via `PostgresService::check()` or `cfg!`.
pub struct PostgresService;
impl cordis::Service for PostgresService {
    fn name(&self) -> &'static str {
        "postgres"
    }
    fn check(&self) -> bool {
        cfg!(feature = "postgres")
    }
}

#[cfg(test)]
mod tests {
    use super::{CollectionInfo, CollectionStats};
    #[cfg(feature = "ares-vector")]
    use super::VectorStoreProvider;
    #[cfg(feature = "ares-vector")]
    use serde_json::json;

    #[test]
    fn collection_stats_serde_roundtrip() {
        let stats = CollectionStats {
            name: "docs".into(),
            document_count: 42,
            dimensions: 384,
            index_size_bytes: Some(1024),
            distance_metric: "cosine".into(),
        };
        let value = serde_json::to_value(&stats).expect("serialize");
        let back: CollectionStats = serde_json::from_value(value).expect("deserialize");
        assert_eq!(back.name, "docs");
        assert_eq!(back.document_count, 42);
        assert_eq!(back.dimensions, 384);
    }

    #[test]
    fn collection_info_serde_roundtrip() {
        let info = CollectionInfo {
            name: "embeddings".into(),
            dimensions: 768,
            document_count: 10,
        };
        let json = serde_json::to_string(&info).expect("serialize");
        let back: CollectionInfo = serde_json::from_str(&json).expect("deserialize");
        assert_eq!(back.name, "embeddings");
        assert_eq!(back.dimensions, 768);
    }

    #[cfg(feature = "ares-vector")]
    #[test]
    fn ares_vector_provider_tagged_json() {
        let provider = VectorStoreProvider::AresVector {
            path: Some("./data/vectors".into()),
        };
        let value = serde_json::to_value(&provider).expect("serialize");
        assert_eq!(value["provider"], json!("aresvector"));
    }
}