robson-core 0.0.2

Rust async agent orchestrator for automated development workflows
Documentation
use crate::entities::conversation;
use crate::llm::LlmMessage;
use anyhow::Result;
use sea_orm::DatabaseConnection;

/// Sanitized, validated input from a gateway (Slack, chat, webhook, etc).
/// Defined here so robson-core remains free of robson-slack dependencies
/// while gateway crates (robson-slack) can produce and return this type.
#[derive(Debug, Clone)]
pub enum SanitizedInput {
    Message {
        text: String,
        channel_id: String,
        user_id: String,
        thread_ts: Option<String>,
        ts: String,
    },
}

pub struct ProcessorOutput {
    pub response_text: String,
}

pub struct Processor {
    db: DatabaseConnection,
}

impl Processor {
    pub fn new(db: DatabaseConnection) -> Self {
        Self { db }
    }

    pub async fn dispatch(&self, input: SanitizedInput) -> Result<ProcessorOutput> {
        let SanitizedInput::Message {
            text,
            channel_id: _,
            user_id: _,
            thread_ts,
            ts,
        } = input;
        let _thread = thread_ts.as_deref().unwrap_or(&ts);
        Ok(ProcessorOutput {
            response_text: format!("Echo: {}", text),
        })
    }

    /// Build LLM context from the last `max_n` conversation turns.
    pub async fn build_context(
        &self,
        channel_id: &str,
        thread_ts: &str,
        max_n: u64,
    ) -> Result<Vec<LlmMessage>> {
        let all = conversation::Model::find_by_thread(&self.db, channel_id, thread_ts).await?;
        let total = all.len();
        let skip = if total as u64 > max_n {
            total - max_n as usize
        } else {
            0
        };

        let messages = all
            .into_iter()
            .skip(skip)
            .map(|m| LlmMessage {
                role: m.role.to_string(),
                content: m.content,
            })
            .collect();

        Ok(messages)
    }
}