llama-rs 0.16.1

A high-performance Rust implementation of llama.cpp - LLM inference engine with full GGUF support
Documentation
//! Streaming events emitted by the council during deliberation.
//!
//! The same enum is used as both the in-process stream type for
//! `Council::deliberate_stream` and the serialized SSE frames for
//! `POST /v1/council/transcript` (one JSON object per `data:` frame,
//! discriminated by the `type` tag).

use serde::{Deserialize, Serialize};

/// Stable, human-readable id for an expert agent ("A", "B", "C", …).
/// Letters are assigned in config order at council init and are stable
/// across rounds.
pub type ExpertId = String;

/// Summary of the council configuration sent in `council_started`.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CouncilStartedSummary {
    pub experts: u32,
    pub synthesizer: ExpertId,
    pub min_rounds: u32,
    pub max_rounds: u32,
}

/// Reason a council failed wholesale.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "code", rename_all = "snake_case")]
pub enum CouncilFailure {
    QuorumLost {
        round: u32,
        required: u32,
        actual: u32,
    },
    SynthesizerFailed {
        message: String,
    },
    EmbedderFailed {
        round: u32,
        message: String,
    },
    Cancelled,
    ConfigError {
        message: String,
    },
    Internal {
        message: String,
    },
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum CouncilEvent {
    CouncilStarted {
        config_summary: CouncilStartedSummary,
    },
    RoundStarted {
        round: u32,
    },
    ExpertStarted {
        round: u32,
        expert_id: ExpertId,
        model: String,
    },
    ExpertToken {
        round: u32,
        expert_id: ExpertId,
        delta: String,
    },
    ExpertCompleted {
        round: u32,
        expert_id: ExpertId,
        tokens: u32,
    },
    ExpertFailed {
        round: u32,
        expert_id: ExpertId,
        error: String,
    },
    RoundCompleted {
        round: u32,
        responded: Vec<ExpertId>,
        failed: Vec<ExpertId>,
    },
    ConvergenceCheck {
        round: u32,
        min_cosine: f32,
        threshold: f32,
        converged: bool,
    },
    SynthesisStarted {
        synthesizer_id: ExpertId,
    },
    FinalToken {
        delta: String,
    },
    CouncilCompleted {
        rounds: u32,
        final_answer_length: u32,
    },
    CouncilFailed {
        error: CouncilFailure,
    },
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn round_started_serializes_with_type_tag() {
        let ev = CouncilEvent::RoundStarted { round: 0 };
        let json = serde_json::to_string(&ev).unwrap();
        assert_eq!(json, r#"{"type":"round_started","round":0}"#);
    }

    #[test]
    fn council_started_serializes_summary() {
        let ev = CouncilEvent::CouncilStarted {
            config_summary: CouncilStartedSummary {
                experts: 3,
                synthesizer: "S".into(),
                min_rounds: 2,
                max_rounds: 4,
            },
        };
        let json = serde_json::to_string(&ev).unwrap();
        assert!(json.contains(r#""type":"council_started""#));
        assert!(json.contains(r#""experts":3"#));
        assert!(json.contains(r#""synthesizer":"S""#));
    }

    #[test]
    fn expert_token_round_trips() {
        let ev = CouncilEvent::ExpertToken {
            round: 1,
            expert_id: "A".into(),
            delta: "hello".into(),
        };
        let json = serde_json::to_string(&ev).unwrap();
        let back: CouncilEvent = serde_json::from_str(&json).unwrap();
        assert_eq!(ev, back);
    }

    #[test]
    fn expert_failed_serializes_error() {
        let ev = CouncilEvent::ExpertFailed {
            round: 0,
            expert_id: "B".into(),
            error: "timeout after 30s".into(),
        };
        let json = serde_json::to_string(&ev).unwrap();
        assert!(json.contains(r#""type":"expert_failed""#));
        assert!(json.contains(r#""error":"timeout after 30s""#));
    }

    #[test]
    fn round_completed_lists_responded_and_failed() {
        let ev = CouncilEvent::RoundCompleted {
            round: 0,
            responded: vec!["A".into(), "C".into()],
            failed: vec!["B".into()],
        };
        let json = serde_json::to_string(&ev).unwrap();
        assert!(json.contains(r#""responded":["A","C"]"#));
        assert!(json.contains(r#""failed":["B"]"#));
    }

    #[test]
    fn convergence_check_includes_threshold_and_decision() {
        let ev = CouncilEvent::ConvergenceCheck {
            round: 1,
            min_cosine: 0.84,
            threshold: 0.92,
            converged: false,
        };
        let json = serde_json::to_string(&ev).unwrap();
        assert!(json.contains(r#""converged":false"#));
        assert!(json.contains(r#""threshold":0.92"#));
    }

    #[test]
    fn final_token_minimal_shape() {
        let ev = CouncilEvent::FinalToken { delta: "Therefore".into() };
        let json = serde_json::to_string(&ev).unwrap();
        assert_eq!(json, r#"{"type":"final_token","delta":"Therefore"}"#);
    }

    #[test]
    fn council_completed_round_trips() {
        let ev = CouncilEvent::CouncilCompleted {
            rounds: 2,
            final_answer_length: 1842,
        };
        let json = serde_json::to_string(&ev).unwrap();
        let back: CouncilEvent = serde_json::from_str(&json).unwrap();
        assert_eq!(ev, back);
    }

    #[test]
    fn council_failed_quorum_lost_has_nested_code() {
        let ev = CouncilEvent::CouncilFailed {
            error: CouncilFailure::QuorumLost {
                round: 1,
                required: 2,
                actual: 1,
            },
        };
        let json = serde_json::to_string(&ev).unwrap();
        assert!(json.contains(r#""type":"council_failed""#));
        assert!(json.contains(r#""error":{"code":"quorum_lost""#));
        assert!(json.contains(r#""round":1"#));
        assert!(json.contains(r#""required":2"#));
        assert!(json.contains(r#""actual":1"#));
    }

    #[test]
    fn council_failed_round_trips_for_each_failure_kind() {
        let cases = [
            CouncilFailure::QuorumLost { round: 0, required: 2, actual: 1 },
            CouncilFailure::SynthesizerFailed { message: "boom".into() },
            CouncilFailure::EmbedderFailed { round: 1, message: "oom".into() },
            CouncilFailure::Cancelled,
            CouncilFailure::ConfigError { message: "bad threshold".into() },
            CouncilFailure::Internal { message: "bug".into() },
        ];
        for failure in cases {
            let ev = CouncilEvent::CouncilFailed { error: failure.clone() };
            let json = serde_json::to_string(&ev).unwrap();
            let back: CouncilEvent = serde_json::from_str(&json).unwrap();
            assert_eq!(ev, back, "round-trip failed for {:?}", failure);
        }
    }
}