use std::collections::HashMap;
use std::sync::Arc;
use parking_lot::Mutex;
use areev_core::error::Hash;
use areev_core::format::deserialize::DeserializedGrain;
use areev_core::types::GrainType;
#[cfg(feature = "llm-rerank")]
#[derive(Clone)]
pub struct InferenceHook(pub Arc<dyn Fn(&InferenceUsage) + Send + Sync>);
#[cfg(feature = "llm-rerank")]
impl InferenceHook {
pub fn new<F>(f: F) -> Self
where
F: Fn(&InferenceUsage) + Send + Sync + 'static,
{
Self(Arc::new(f))
}
pub fn call(&self, usage: &InferenceUsage) {
(self.0)(usage);
}
}
#[cfg(feature = "llm-rerank")]
impl std::fmt::Debug for InferenceHook {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("InferenceHook").finish_non_exhaustive()
}
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RecallSource {
Primary,
Expansion,
Census,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct RebuildReport {
pub grains_scanned: usize,
pub fts_indexed: usize,
pub vectors_indexed: usize,
pub errors: Vec<String>,
pub elapsed_ms: u64,
}
#[derive(Debug, serde::Serialize)]
pub struct DetailedStats {
pub total_grains: usize,
pub disk_space_bytes: u64,
pub namespaces: Vec<String>,
pub users: Vec<String>,
pub type_counts: std::collections::BTreeMap<String, usize>,
pub audit_entries: Option<usize>,
pub has_encryption: bool,
pub has_policy: bool,
pub vector_mapping_loaded: bool,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ConflictStatus {
Current,
Outdated,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SupersessionStatus {
Current,
Superseded,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TopicCoverage {
None,
Partial,
Full,
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct ScoreBreakdown {
pub bm25_rank: Option<usize>,
pub vector_score: Option<f64>,
pub rrf_score: f64,
pub interference_penalty: Option<f64>,
pub recency_decay: Option<f64>,
pub session_affinity: Option<f64>,
pub subject_affinity: Option<f64>,
pub target_date_proximity: Option<f64>,
pub supersession_demotion: Option<f64>,
pub temporal_decay_boost: Option<f64>,
pub final_score: f64,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ForkGroupInfo {
pub namespace: String,
pub subject: String,
pub relation: String,
pub heads: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct SearchHit {
pub grain: DeserializedGrain,
pub score: f64,
pub hash: Hash,
pub score_breakdown: Option<ScoreBreakdown>,
#[cfg(feature = "rerank")]
pub rerank_score: Option<f32>,
#[cfg(feature = "llm-rerank")]
pub llm_rerank_score: Option<f32>,
pub explanation: Option<String>,
pub scope_depth: Option<u8>,
pub source_namespace: Option<String>,
pub relative_time: Option<String>,
pub conflict_status: Option<ConflictStatus>,
pub supersession_status: Option<SupersessionStatus>,
pub superseded_by_hash: Option<Hash>,
pub recall_source: Option<RecallSource>,
}
#[derive(Debug, Clone)]
pub struct SessionBootstrap {
pub session_id: String,
pub state: Option<DeserializedGrain>,
pub active_goals: Vec<DeserializedGrain>,
pub recent_tools: Vec<DeserializedGrain>,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct ToolSummary {
pub total_calls: usize,
pub successful: usize,
pub failed: usize,
pub total_duration_ms: u64,
pub by_tool: HashMap<String, ToolStats>,
pub error_patterns: Vec<(String, usize)>,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct ToolStats {
pub calls: usize,
pub failures: usize,
pub total_duration_ms: u64,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct ConsolidationResult {
pub session_id: String,
pub groups: Vec<ConsolidationGroupInfo>,
pub total_analyzed: usize,
pub threshold: f64,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct ConsolidationGroupInfo {
pub canonical_hash: Hash,
pub duplicate_hashes: Vec<Hash>,
pub similarity: f64,
pub confirmation_count: usize,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct CompiledContext {
pub session_id: String,
pub state: Option<DeserializedGrain>,
pub goals: Vec<DeserializedGrain>,
pub tools: Vec<DeserializedGrain>,
pub facts: Vec<DeserializedGrain>,
pub estimated_tokens: usize,
pub token_budget: usize,
pub truncated: bool,
}
#[derive(Debug, Clone)]
pub struct RecallChainResult {
pub sub_queries: Vec<String>,
pub sub_results: Vec<Vec<SearchHit>>,
pub merged_hits: Vec<SearchHit>,
pub reasoning: String,
}
#[derive(Debug, Clone, serde::Serialize)]
pub enum EngineEvent {
Added { hash: Hash, grain_type: GrainType },
Forgotten { hash: Hash },
Superseded { old_hash: Hash, new_hash: Hash },
MemoriesExtracted {
source_hash: Hash,
memory_hashes: Vec<Hash>,
},
}
#[derive(Debug, Default, Clone)]
pub struct AddOptions {
pub extract_event_date: Option<bool>,
pub auto_relate: Option<bool>,
pub sync: Option<bool>,
}
#[derive(Debug, Clone)]
pub struct AddResult {
pub hash: areev_core::error::Hash,
pub extracted_count: usize,
pub extraction_warnings: Vec<String>,
pub marker_status: Option<ExtractionMarkerStatus>,
}
impl AddResult {
pub fn plain(hash: areev_core::error::Hash) -> Self {
Self {
hash,
extracted_count: 0,
extraction_warnings: vec![],
marker_status: None,
}
}
pub fn into_hash(self) -> areev_core::error::Hash {
self.hash
}
}
impl From<AddResult> for areev_core::error::Hash {
fn from(r: AddResult) -> Self {
r.hash
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
#[derive(Default)]
pub enum TemporalField {
#[default]
CreatedAt,
EventDate,
Both,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct WriteStatus {
pub pending_writes: usize,
}
#[derive(Debug, Clone)]
pub struct DiversityConfig {
pub method: DiversityMethod,
}
#[derive(Debug, Clone)]
pub enum DiversityMethod {
Mmr { lambda: f32 },
Threshold(f32),
}
impl DiversityConfig {
pub fn mmr() -> Self {
Self {
method: DiversityMethod::Mmr { lambda: 0.5 },
}
}
pub fn mmr_with_lambda(lambda: f32) -> Self {
Self {
method: DiversityMethod::Mmr {
lambda: lambda.clamp(0.0, 1.0),
},
}
}
pub fn threshold(t: f32) -> Self {
Self {
method: DiversityMethod::Threshold(t.clamp(0.0, 1.0)),
}
}
}
#[derive(Debug, Clone)]
pub struct ExhaustiveConfig {
pub max_rounds: u8,
pub candidate_multiplier: u16,
pub use_entity_lookup: bool,
pub min_score: f64,
pub max_grains_per_round: u16,
}
impl Default for ExhaustiveConfig {
fn default() -> Self {
Self {
max_rounds: 3,
candidate_multiplier: 10,
use_entity_lookup: true,
min_score: 0.60,
max_grains_per_round: 20,
}
}
}
impl ExhaustiveConfig {
pub fn validate(&mut self) {
self.max_rounds = self.max_rounds.clamp(1, 5);
self.candidate_multiplier = self.candidate_multiplier.clamp(5, 50);
self.min_score = self.min_score.clamp(0.0, 1.0);
self.max_grains_per_round = self.max_grains_per_round.clamp(1, 100);
}
}
#[derive(Debug, Clone)]
pub struct SessionCensusConfig {
pub min_per_session: u8,
pub min_score: f64,
pub max_additional_queries: u8,
}
impl Default for SessionCensusConfig {
fn default() -> Self {
Self {
min_per_session: 2,
min_score: 0.35,
max_additional_queries: 10,
}
}
}
impl SessionCensusConfig {
pub fn validate(&mut self) {
self.min_per_session = self.min_per_session.clamp(1, 10);
self.min_score = self.min_score.clamp(0.0, 1.0);
self.max_additional_queries = self.max_additional_queries.clamp(1, 50);
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GrainTypeDiversityConfig {
pub min_per_type: u8,
pub max_reservation_pct: f32,
}
impl Default for GrainTypeDiversityConfig {
fn default() -> Self {
Self {
min_per_type: 1,
max_reservation_pct: 0.30,
}
}
}
impl GrainTypeDiversityConfig {
pub fn validate(&mut self) {
self.min_per_type = self.min_per_type.clamp(1, 10);
self.max_reservation_pct = self.max_reservation_pct.clamp(0.05, 0.50);
}
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "http", derive(utoipa::ToSchema))]
pub struct SessionCensusMetadata {
pub total_sessions: usize,
pub represented_sessions: usize,
pub census_queries_issued: usize,
pub grains_added: usize,
pub session_stats: Vec<CensusSessionStat>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "http", derive(utoipa::ToSchema))]
pub struct CensusSessionStat {
pub namespace: String,
pub grains_found: usize,
pub grains_merged: usize,
pub top_score: f64,
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "http", derive(utoipa::ToSchema))]
pub struct ExhaustiveMetadata {
pub rounds_executed: u8,
pub entities_found: Vec<String>,
pub initial_unique_count: usize,
pub final_unique_count: usize,
pub round_stats: Vec<ExhaustiveRoundStat>,
pub converged: bool,
#[serde(default)]
pub expansion_grains_filtered: usize,
#[serde(default)]
pub expansion_grains_budget_capped: usize,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub expansion_score_cap: Option<f64>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "http", derive(utoipa::ToSchema))]
pub struct ExhaustiveRoundStat {
pub round: u8,
pub queries_issued: usize,
pub new_hashes: usize,
#[serde(default)]
pub filtered_by_min_score: usize,
#[serde(default)]
pub budget_capped: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct HybridParams {
pub rrf_k: u32,
pub bm25_topk: u32,
pub vec_topk: u32,
pub final_topk: u32,
}
impl Default for HybridParams {
fn default() -> Self {
Self {
rrf_k: 60,
bm25_topk: 200,
vec_topk: 200,
final_topk: 20,
}
}
}
impl HybridParams {
pub fn clamped(self, range: &HybridParamsRange) -> Self {
Self {
rrf_k: self.rrf_k.clamp(range.rrf_k_min, range.rrf_k_max),
bm25_topk: self
.bm25_topk
.clamp(range.bm25_topk_min, range.bm25_topk_max),
vec_topk: self.vec_topk.clamp(range.vec_topk_min, range.vec_topk_max),
final_topk: self
.final_topk
.clamp(range.final_topk_min, range.final_topk_max),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct HybridParamsRange {
pub rrf_k_min: u32,
pub rrf_k_max: u32,
pub bm25_topk_min: u32,
pub bm25_topk_max: u32,
pub vec_topk_min: u32,
pub vec_topk_max: u32,
pub final_topk_min: u32,
pub final_topk_max: u32,
}
impl Default for HybridParamsRange {
fn default() -> Self {
Self {
rrf_k_min: 10,
rrf_k_max: 200,
bm25_topk_min: 10,
bm25_topk_max: 500,
vec_topk_min: 10,
vec_topk_max: 500,
final_topk_min: 1,
final_topk_max: 100,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SortKey {
pub field: String,
pub descending: bool,
}
#[derive(Debug, Default, Clone)]
pub struct RecallParams {
pub query: Option<String>,
pub subject: Option<String>,
pub relation: Option<String>,
pub object: Option<String>,
pub subject_in: Option<Vec<String>>,
pub relation_in: Option<Vec<String>>,
pub object_in: Option<Vec<String>>,
pub namespace: Option<String>,
pub scope_path: Option<String>,
pub(crate) namespaces: Option<Vec<String>>,
pub include_siblings: Option<bool>,
pub user_id: Option<String>,
pub session_id: Option<String>,
pub grain_type: Option<GrainType>,
pub time_start: Option<i64>,
pub time_end: Option<i64>,
pub confidence_threshold: Option<f64>,
pub limit: Option<usize>,
pub order_by: Option<SortKey>,
pub exclude_superseded: Option<bool>,
pub temporal_expr: Option<String>,
pub tags: Option<Vec<String>>,
pub exclude_tags: Option<Vec<String>>,
pub importance_threshold: Option<f64>,
pub include_contradicted: Option<bool>,
pub detect_contradictions: Option<bool>,
pub embedding: Option<Vec<f32>>,
pub candidate_limit: Option<usize>,
pub min_score: Option<f64>,
pub score_breakdown: Option<bool>,
pub diversity: Option<DiversityConfig>,
pub rerank: Option<RerankConfig>,
#[cfg(feature = "llm-rerank")]
pub llm_rerank: Option<crate::store_types::LlmRerankConfig>,
#[cfg(feature = "llm-rerank")]
pub inference_hook: Option<InferenceHook>,
pub record_provenance: Option<bool>,
pub explanation: Option<bool>,
pub subject_contains: Option<String>,
pub object_contains: Option<String>,
pub recency_weight: Option<f64>,
pub conflict_resolution: Option<bool>,
pub entity: Option<String>,
pub query_expansion: Option<bool>,
pub hyde: Option<bool>,
pub min_per_namespace: Option<usize>,
pub max_namespaces: Option<usize>,
pub deduplicate: Option<bool>,
pub deduplicate_threshold: Option<f64>,
pub temporal_field: Option<TemporalField>,
pub include_sources: Option<bool>,
pub annotate_relative_time: Option<bool>,
pub reference_date: Option<i64>,
pub session_affinity_boost: Option<f64>,
pub subject_affinity_boost: Option<f64>,
pub multi_hop: Option<u8>,
pub target_date: Option<i64>,
pub target_date_weight: Option<f64>,
pub conflict_similarity_threshold: Option<f64>,
pub count_entities: Option<bool>,
pub query_decompose: Option<bool>,
pub aggregation_intent: Option<bool>,
pub preference_enrichment: Option<bool>,
pub(crate) _decompose_depth: u8,
pub exhaustive: Option<ExhaustiveConfig>,
pub session_census: Option<SessionCensusConfig>,
pub run_id: Option<String>,
pub hybrid: Option<HybridParams>,
pub min_proficiency: Option<f64>,
pub skill_transferable: Option<bool>,
pub skill_domain: Option<String>,
pub holder_did: Option<String>,
}
impl RecallParams {
pub fn new() -> Self {
Self::default()
}
pub fn needs_payload_postfilter(&self) -> bool {
self.confidence_threshold.is_some()
|| self.namespaces.is_some()
|| self.tags.is_some()
|| self.exclude_tags.is_some()
|| self.subject_contains.is_some()
|| self.object_contains.is_some()
|| self.include_contradicted == Some(false)
|| self.entity.is_some()
|| self.subject.is_some()
|| self.relation.is_some()
|| self.object.is_some()
|| self.subject_in.is_some()
|| self.relation_in.is_some()
|| self.object_in.is_some()
|| self.min_proficiency.is_some()
|| self.skill_domain.is_some()
|| self.skill_transferable.is_some()
|| self.holder_did.is_some()
|| ((self.time_start.is_some() || self.time_end.is_some())
&& !matches!(
self.temporal_field.unwrap_or_default(),
TemporalField::CreatedAt
))
}
pub fn query(mut self, q: &str) -> Self {
self.query = Some(q.to_string());
self
}
pub fn subject(mut self, s: &str) -> Self {
self.subject = Some(s.to_string());
self
}
pub fn relation(mut self, r: &str) -> Self {
self.relation = Some(r.to_string());
self
}
pub fn object(mut self, o: &str) -> Self {
self.object = Some(o.to_string());
self
}
pub fn namespace(mut self, ns: &str) -> Self {
self.namespace = Some(ns.to_string());
self
}
pub fn user_id(mut self, uid: &str) -> Self {
self.user_id = Some(uid.to_string());
self
}
pub fn scope_path(mut self, path: &str) -> Self {
self.scope_path = Some(path.to_string());
self
}
pub fn include_siblings(mut self, include: bool) -> Self {
self.include_siblings = Some(include);
self
}
pub fn grain_type(mut self, gt: GrainType) -> Self {
self.grain_type = Some(gt);
self
}
pub fn time_range(mut self, start: i64, end: i64) -> Self {
self.time_start = Some(start);
self.time_end = Some(end);
self
}
pub fn confidence_threshold(mut self, threshold: f64) -> Self {
self.confidence_threshold = Some(threshold);
self
}
pub fn limit(mut self, n: usize) -> Self {
self.limit = Some(n);
self
}
pub fn run_id(mut self, run_id: &str) -> Self {
self.run_id = Some(run_id.to_string());
self
}
pub fn temporal_expr(mut self, expr: &str) -> Self {
self.temporal_expr = Some(expr.to_string());
self
}
pub fn tags(mut self, tags: Vec<String>) -> Self {
self.tags = Some(tags);
self
}
pub fn exclude_tags(mut self, tags: Vec<String>) -> Self {
self.exclude_tags = Some(tags);
self
}
pub fn importance_threshold(mut self, threshold: f64) -> Self {
self.importance_threshold = Some(threshold);
self
}
pub fn min_proficiency(mut self, threshold: f64) -> Self {
self.min_proficiency = Some(threshold);
self
}
pub fn skill_transferable(mut self, transferable: bool) -> Self {
self.skill_transferable = Some(transferable);
self
}
pub fn skill_domain(mut self, domain: &str) -> Self {
self.skill_domain = Some(domain.to_string());
self
}
pub fn holder_did(mut self, holder_did: &str) -> Self {
self.holder_did = Some(holder_did.to_string());
self
}
pub fn include_contradicted(mut self, include: bool) -> Self {
self.include_contradicted = Some(include);
self
}
pub fn embedding(mut self, vec: Vec<f32>) -> Self {
self.embedding = Some(vec);
self
}
pub fn detect_contradictions(mut self, detect: bool) -> Self {
self.detect_contradictions = Some(detect);
self
}
pub fn candidate_limit(mut self, k: usize) -> Self {
self.candidate_limit = Some(k);
self
}
pub fn min_score(mut self, s: f64) -> Self {
self.min_score = Some(s.clamp(0.0, 1.0));
self
}
pub fn with_score_breakdown(mut self) -> Self {
self.score_breakdown = Some(true);
self
}
pub fn diversity(mut self, d: DiversityConfig) -> Self {
self.diversity = Some(d);
self
}
pub fn rerank(mut self, cfg: RerankConfig) -> Self {
self.rerank = Some(cfg);
self
}
#[cfg(feature = "llm-rerank")]
pub fn llm_rerank(mut self, cfg: crate::store_types::LlmRerankConfig) -> Self {
self.llm_rerank = Some(cfg);
self
}
pub fn score_breakdown(mut self, enabled: bool) -> Self {
self.score_breakdown = Some(enabled);
self
}
pub fn explanation(mut self, enabled: bool) -> Self {
self.explanation = Some(enabled);
self
}
pub fn record_provenance(mut self, enabled: bool) -> Self {
self.record_provenance = Some(enabled);
self
}
pub fn exclude_superseded(mut self, exclude: bool) -> Self {
self.exclude_superseded = Some(exclude);
self
}
pub fn recency_weight(mut self, w: f64) -> Self {
self.recency_weight = Some(w.clamp(0.0, 1.0));
self
}
pub fn conflict_resolution(mut self, enabled: bool) -> Self {
self.conflict_resolution = Some(enabled);
self
}
pub fn entity(mut self, e: &str) -> Self {
self.entity = Some(e.to_string());
self
}
pub fn query_expansion(mut self, enabled: bool) -> Self {
self.query_expansion = Some(enabled);
self
}
pub fn hyde(mut self, enabled: bool) -> Self {
self.hyde = Some(enabled);
self
}
pub fn min_per_namespace(mut self, n: usize) -> Self {
self.min_per_namespace = Some(n);
self
}
pub fn max_namespaces(mut self, n: usize) -> Self {
self.max_namespaces = Some(n);
self
}
pub fn deduplicate(mut self, enabled: bool) -> Self {
self.deduplicate = Some(enabled);
self
}
pub fn deduplicate_threshold(mut self, threshold: f64) -> Self {
self.deduplicate_threshold = Some(threshold.clamp(0.0, 1.0));
self
}
pub fn subject_contains(mut self, pattern: impl Into<String>) -> Self {
self.subject_contains = Some(pattern.into());
self
}
pub fn object_contains(mut self, pattern: impl Into<String>) -> Self {
self.object_contains = Some(pattern.into());
self
}
pub fn temporal_field(mut self, tf: TemporalField) -> Self {
self.temporal_field = Some(tf);
self
}
pub fn include_sources(mut self, enabled: bool) -> Self {
self.include_sources = Some(enabled);
self
}
pub fn annotate_relative_time(mut self, enabled: bool) -> Self {
self.annotate_relative_time = Some(enabled);
self
}
pub fn reference_date(mut self, reference_ms: i64) -> Self {
self.reference_date = Some(reference_ms);
self
}
pub fn session_affinity_boost(mut self, boost: f64) -> Self {
self.session_affinity_boost = Some(boost.clamp(0.0, 1.0));
self
}
pub fn subject_affinity_boost(mut self, boost: f64) -> Self {
self.subject_affinity_boost = Some(boost.clamp(0.0, 1.0));
self
}
pub fn multi_hop(mut self, hops: u8) -> Self {
self.multi_hop = Some(hops.clamp(1, 3));
self
}
pub fn target_date(mut self, ts: i64) -> Self {
self.target_date = Some(ts);
self
}
pub fn target_date_weight(mut self, w: f64) -> Self {
self.target_date_weight = Some(w.clamp(0.0, 1.0));
self
}
pub fn conflict_similarity_threshold(mut self, t: f64) -> Self {
self.conflict_similarity_threshold = Some(t.clamp(0.0, 1.0));
self
}
pub fn count_entities(mut self, enabled: bool) -> Self {
self.count_entities = Some(enabled);
self
}
pub fn query_decompose(mut self, v: bool) -> Self {
self.query_decompose = Some(v);
self
}
pub fn aggregation_intent(mut self, v: bool) -> Self {
self.aggregation_intent = Some(v);
self
}
pub fn preference_enrichment(mut self, v: bool) -> Self {
self.preference_enrichment = Some(v);
self
}
pub fn subject_in(mut self, values: Vec<String>) -> Self {
self.subject_in = Some(values);
self
}
pub fn relation_in(mut self, values: Vec<String>) -> Self {
self.relation_in = Some(values);
self
}
pub fn object_in(mut self, values: Vec<String>) -> Self {
self.object_in = Some(values);
self
}
pub fn exhaustive(mut self, config: ExhaustiveConfig) -> Self {
self.exhaustive = Some(config);
self
}
pub fn session_census(mut self, config: SessionCensusConfig) -> Self {
self.session_census = Some(config);
self
}
}
#[allow(dead_code)] const GRAIN_CACHE_SHARDS: usize = 16;
#[allow(dead_code)] pub(crate) struct GrainCache {
shards: Vec<Mutex<lru::LruCache<Hash, Arc<DeserializedGrain>>>>,
}
#[allow(dead_code)] impl GrainCache {
pub(crate) fn new(total_capacity: usize) -> Self {
let per_shard = (total_capacity / GRAIN_CACHE_SHARDS).max(1);
let shards = (0..GRAIN_CACHE_SHARDS)
.map(|_| {
Mutex::new(lru::LruCache::new(
std::num::NonZeroUsize::new(per_shard).unwrap(),
))
})
.collect();
GrainCache { shards }
}
fn shard_index(hash: &Hash) -> usize {
(hash.as_bytes()[0] as usize) % GRAIN_CACHE_SHARDS
}
pub(crate) fn get(&self, hash: &Hash) -> Option<Arc<DeserializedGrain>> {
let idx = Self::shard_index(hash);
self.shards[idx].lock().get(hash).cloned()
}
pub(crate) fn put(&self, hash: Hash, grain: Arc<DeserializedGrain>) {
let idx = Self::shard_index(&hash);
self.shards[idx].lock().put(hash, grain);
}
pub(crate) fn pop(&self, hash: &Hash) {
let idx = Self::shard_index(hash);
self.shards[idx].lock().pop(hash);
}
}
#[derive(Debug, Clone)]
pub struct VersionEntry {
pub hash: Hash,
pub object: String,
pub created_at: i64,
pub confidence: f64,
pub superseded_by: Option<Hash>,
}
#[derive(Debug, Clone)]
pub struct RerankConfig { pub candidate_k: usize, pub return_n: Option<usize>, pub min_rerank_score: Option<f32>, pub model: Option<String> }
impl Default for RerankConfig { fn default() -> Self { RerankConfig { candidate_k: 30, return_n: None, min_rerank_score: None, model: None } } }
#[derive(Debug, Clone)]
pub struct LlmRerankConfig { pub candidate_k: usize, pub return_n: Option<usize>, pub user_id: Option<String>, pub model: Option<String> }
impl Default for LlmRerankConfig { fn default() -> Self { LlmRerankConfig { candidate_k: 20, return_n: None, user_id: None, model: None } } }
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ErasureProof { pub user_id: String, pub count: u64, pub key_fingerprint: String, pub timestamp: i64, pub user_record_deleted: bool }
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct SubjectReportResult {
pub identity_names: Vec<String>,
pub grains: Vec<serde_json::Value>,
}
#[derive(Debug, Clone)]
pub struct InferenceUsage {
pub input_tokens: u32,
pub output_tokens: u32,
pub provider_cost_usd: f64,
pub model: String,
pub provider: &'static str,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum ExtractionMarkerStatus {
Pending = 0x00,
InProgress = 0x01,
Complete = 0x02,
Failed = 0x03,
}