butterfly-bot 0.2.6

Butterfly Bot is an opinionated personal-ops AI assistant built for people who want results, not setup overhead.
Documentation
use async_trait::async_trait;
use tokio::sync::Mutex;

use crate::error::Result;
use crate::interfaces::brain::{BrainContext, BrainEvent, BrainPlugin};

#[derive(Debug, Clone)]
pub struct ProbabilisticResult {
    pub probability: f32,
    pub confidence_interval: (f32, f32),
    pub reasoning: String,
}

pub struct ProbabilisticReasoningBrain {
    last_result: Mutex<Option<ProbabilisticResult>>,
}

impl ProbabilisticReasoningBrain {
    pub fn new() -> Self {
        Self {
            last_result: Mutex::new(None),
        }
    }

    pub async fn last_result(&self) -> Option<ProbabilisticResult> {
        let guard = self.last_result.lock().await;
        guard.clone()
    }

    fn involves_uncertainty(message: &str) -> bool {
        let lower = message.to_lowercase();
        [
            "probability",
            "chance",
            "likely",
            "risk",
            "odds",
            "uncertain",
        ]
        .iter()
        .any(|token| lower.contains(token))
    }

    fn naive_estimate(message: &str) -> ProbabilisticResult {
        let lower = message.to_lowercase();
        let base = if lower.contains("unlikely") {
            0.25
        } else if lower.contains("likely") {
            0.7
        } else {
            0.5
        };
        ProbabilisticResult {
            probability: base,
            confidence_interval: (base - 0.1, base + 0.1),
            reasoning: "Naive uncertainty estimate based on language".to_string(),
        }
    }
}

#[async_trait]
impl BrainPlugin for ProbabilisticReasoningBrain {
    fn name(&self) -> &str {
        "probabilistic_reasoning"
    }

    fn description(&self) -> &str {
        "Provides simple probabilistic estimates from language cues"
    }

    async fn on_event(&self, event: BrainEvent, _ctx: &BrainContext) -> Result<()> {
        if let BrainEvent::UserMessage { text, .. } = event {
            if Self::involves_uncertainty(&text) {
                let result = Self::naive_estimate(&text);
                let mut guard = self.last_result.lock().await;
                *guard = Some(result);
            }
        }
        Ok(())
    }
}