#[cfg(feature = "sqlx")]
use std::sync::Arc;
#[cfg(feature = "sqlx")]
use systemprompt_identifiers::EventOutboxId;
use systemprompt_identifiers::FactKindId;
#[cfg(feature = "sqlx")]
use systemprompt_models::brain::BrainEvent;
use systemprompt_models::brain::{
BrainEnvelope, BrainFact, BrainModelRequest, BrainModelResponse, ExtractionInput,
ExtractionOutput, FactCandidate, FactSource, ImportanceConfig, KindDecl, RecallCtx, SourceText,
};
#[cfg(feature = "sqlx")]
use super::errors::BrainSinkError;
use super::errors::{BrainExtractError, BrainModelError, BrainValidateError, SourceContentError};
#[cfg(feature = "sqlx")]
#[async_trait::async_trait]
pub trait BrainSink: Send + Sync {
fn is_available(&self) -> bool;
async fn emit(
&self,
conn: &mut sqlx::PgConnection,
event: &BrainEvent,
) -> Result<EventOutboxId, BrainSinkError>;
}
#[cfg(feature = "sqlx")]
pub type DynBrainSink = Arc<dyn BrainSink>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FilterVerdict {
Gather { kinds: Vec<FactKindId> },
Ignore,
Abstain,
}
pub trait EventFilter: Send + Sync {
fn name(&self) -> &'static str;
fn decide(&self, envelope: &BrainEnvelope) -> FilterVerdict;
}
#[async_trait::async_trait]
pub trait FactExtractor: Send + Sync {
fn name(&self) -> &'static str;
fn handles(&self, kind: &KindDecl) -> bool;
async fn extract(&self, input: &ExtractionInput)
-> Result<ExtractionOutput, BrainExtractError>;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ValidationVerdict {
Accept,
Reject { reason: String },
Dispute { reason: String },
}
#[async_trait::async_trait]
pub trait FactValidator: Send + Sync {
fn name(&self) -> &'static str;
async fn validate(
&self,
candidate: &FactCandidate,
kind: &KindDecl,
text: Option<&SourceText>,
) -> Result<ValidationVerdict, BrainValidateError>;
}
pub trait ImportanceModel: Send + Sync {
fn name(&self) -> &'static str;
fn base(&self, candidate: &FactCandidate, config: &ImportanceConfig) -> Option<f64>;
fn in_context(
&self,
fact: &BrainFact,
ctx: &RecallCtx,
config: &ImportanceConfig,
) -> Option<f64>;
}
#[async_trait::async_trait]
pub trait SourceContent: Send + Sync {
fn name(&self) -> &'static str;
fn handles(&self, source: &FactSource) -> bool;
async fn fetch(&self, source: &FactSource) -> Result<Option<SourceText>, SourceContentError>;
}
#[async_trait::async_trait]
pub trait BrainModelClient: Send + Sync {
async fn complete(
&self,
request: BrainModelRequest,
) -> Result<BrainModelResponse, BrainModelError>;
}