use std::sync::Arc;
use crate::access_control::{AccessControlManager, AiFeature, TokenHolder};
use crate::ai_evaluator::{AiCommitmentVerifier, AiEvaluator, AiFraudDetector, EvaluatorConfig};
use crate::error::{AiError, Result};
use crate::fraud::FraudAnalysisService;
use crate::github::{GitHubClient, GitHubConfig, GitHubVerifier};
use crate::knowledge_base::KnowledgeBase;
use crate::llm::LlmClient;
use crate::oracle::{AiOracle, OracleConfig};
use crate::reputation_predictor::ReputationPredictor;
use crate::token_analyzer::TokenAnalyzer;
#[derive(Debug, Clone, Default)]
pub struct AiServiceConfig {
#[allow(clippy::derivable_impls)]
pub evaluator_config: EvaluatorConfig,
pub oracle_config: Option<OracleConfig>,
pub github_config: Option<GitHubConfig>,
pub enable_access_control: bool,
}
pub struct AiServiceHub {
llm: Arc<LlmClient>,
config: AiServiceConfig,
knowledge_base: KnowledgeBase,
access_control: Option<AccessControlManager>,
}
impl AiServiceHub {
#[must_use]
pub fn new(llm: Arc<LlmClient>) -> Self {
Self::with_config(llm, AiServiceConfig::default())
}
#[must_use]
pub fn with_config(llm: Arc<LlmClient>, config: AiServiceConfig) -> Self {
let knowledge_base = KnowledgeBase::new();
let access_control = if config.enable_access_control {
Some(AccessControlManager::new())
} else {
None
};
Self {
llm,
config,
knowledge_base,
access_control,
}
}
#[must_use]
pub fn evaluator_config(&self) -> &EvaluatorConfig {
&self.config.evaluator_config
}
#[must_use]
pub fn oracle_config(&self) -> Option<&OracleConfig> {
self.config.oracle_config.as_ref()
}
#[must_use]
pub fn github_config(&self) -> Option<&GitHubConfig> {
self.config.github_config.as_ref()
}
#[must_use]
pub fn evaluator(&self) -> AiEvaluator {
AiEvaluator::with_config((*self.llm).clone(), self.config.evaluator_config.clone())
}
#[must_use]
pub fn verifier(&self) -> AiCommitmentVerifier {
AiCommitmentVerifier::new((*self.llm).clone())
}
#[must_use]
pub fn fraud_detector(&self) -> AiFraudDetector {
AiFraudDetector::new((*self.llm).clone())
}
#[must_use]
pub fn fraud_service(&self) -> FraudAnalysisService {
FraudAnalysisService::new()
}
#[must_use]
pub fn reputation_predictor(&self) -> ReputationPredictor {
ReputationPredictor::new((*self.llm).clone())
}
#[must_use]
pub fn token_analyzer(&self) -> TokenAnalyzer {
TokenAnalyzer::new((*self.llm).clone())
}
pub fn oracle(&self) -> Result<AiOracle> {
let config = self.config.oracle_config.clone().ok_or_else(|| {
AiError::Configuration(
"Oracle not configured. Use with_oracle() in builder.".to_string(),
)
})?;
Ok(AiOracle::new(config))
}
pub fn github_verifier(&self) -> Result<GitHubVerifier> {
let github_config = self.config.github_config.clone().ok_or_else(|| {
AiError::Configuration(
"GitHub integration not configured. Use with_github() in builder.".to_string(),
)
})?;
let github_client = GitHubClient::new(github_config)?;
Ok(GitHubVerifier::new(github_client))
}
#[must_use]
pub fn can_access_feature(
&self,
holder: &TokenHolder,
feature: AiFeature,
) -> Option<Result<bool>> {
self.access_control
.as_ref()
.map(|ac| ac.can_access_feature(holder, feature))
}
pub fn record_usage(&mut self, holder: &TokenHolder, feature: AiFeature) -> Option<Result<()>> {
self.access_control
.as_mut()
.map(|ac| ac.record_usage(holder, feature))
}
#[must_use]
pub fn knowledge_base(&self) -> &KnowledgeBase {
&self.knowledge_base
}
pub fn knowledge_base_mut(&mut self) -> &mut KnowledgeBase {
&mut self.knowledge_base
}
#[must_use]
pub fn llm_client(&self) -> &Arc<LlmClient> {
&self.llm
}
}
pub struct AiServiceBuilder {
llm: Arc<LlmClient>,
config: AiServiceConfig,
}
impl AiServiceBuilder {
#[must_use]
pub fn new(llm: Arc<LlmClient>) -> Self {
Self {
llm,
config: AiServiceConfig::default(),
}
}
#[must_use]
pub fn evaluator_config(mut self, config: EvaluatorConfig) -> Self {
self.config.evaluator_config = config;
self
}
#[must_use]
pub fn with_oracle(mut self, config: OracleConfig) -> Self {
self.config.oracle_config = Some(config);
self
}
#[must_use]
pub fn with_github(mut self, config: GitHubConfig) -> Self {
self.config.github_config = Some(config);
self
}
#[must_use]
pub fn with_access_control(mut self) -> Self {
self.config.enable_access_control = true;
self
}
#[must_use]
pub fn build(self) -> AiServiceHub {
AiServiceHub::with_config(self.llm, self.config)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::llm::OpenAiClient;
#[test]
fn test_service_builder() {
let openai = OpenAiClient::with_default_model("test-key");
let llm_client = Arc::new(LlmClient::new(Box::new(openai)));
let service = AiServiceBuilder::new(llm_client)
.with_access_control()
.build();
assert!(service.access_control.is_some());
assert!(service.config.oracle_config.is_none());
assert!(service.config.github_config.is_none());
}
#[test]
fn test_service_with_oracle() {
let openai = OpenAiClient::with_default_model("test-key");
let llm_client = Arc::new(LlmClient::new(Box::new(openai)));
let oracle_config = OracleConfig::default();
let service = AiServiceBuilder::new(llm_client)
.with_oracle(oracle_config)
.build();
assert!(service.config.oracle_config.is_some());
assert!(service.oracle().is_ok());
}
#[test]
fn test_service_with_github() {
let openai = OpenAiClient::with_default_model("test-key");
let llm_client = Arc::new(LlmClient::new(Box::new(openai)));
let github_config = GitHubConfig::default();
let service = AiServiceBuilder::new(llm_client)
.with_github(github_config)
.build();
assert!(service.config.github_config.is_some());
assert!(service.github_verifier().is_ok());
}
#[test]
fn test_default_service() {
let openai = OpenAiClient::with_default_model("test-key");
let llm_client = Arc::new(LlmClient::new(Box::new(openai)));
let service = AiServiceHub::new(llm_client);
assert!(service.access_control.is_none());
assert!(service.config.oracle_config.is_none());
assert!(service.config.github_config.is_none());
}
}