1#![warn(missing_docs)]
74#![allow(clippy::module_name_repetitions)]
75#![allow(clippy::must_use_candidate)]
76
77pub mod agent;
78#[cfg(feature = "beleth")]
79pub mod beleth_integration;
80pub mod consensus;
81pub mod context;
82pub mod fault;
83pub mod field;
84pub mod orchestrator;
85pub mod quality;
86pub mod spectral_merge;
87pub mod speculative;
88
89#[cfg(test)]
90mod tests;
91
92use std::sync::Arc;
93
94use parking_lot::RwLock;
95use thiserror::Error;
96
97pub use agent::{AgentConfig, AgentState, LegionAgent};
98#[cfg(feature = "beleth")]
99pub use beleth_integration::{
100 AgentContribution, AgentProposal, LegionBackend, LegionBackendError, LegionReactBackend,
101 MultiPerspectiveThought, Perspective, PerspectiveConfig, ResolutionMethod, ResolvedAction,
102};
103pub use consensus::{
104 AgentContribution as ConsensusContribution, ConsensusResult, ConsensusStrategy,
105 InterferenceConfig, InterferenceConsensus, InterferenceResult,
106};
107pub use context::{ContextFragment, FragmentId, SharedContext};
108pub use fault::{
109 AgentHealth, DegradationCause, DegradationEvent, DegradationManager, FailureReason,
110 FaultConfig, HealthCheckResult, HealthMonitor, HealthStats, HealthStatusChange,
111 RecoveryManager, RecoveryOperation, RecoveryStats, RecoveryType, RespawnRequest,
112};
113pub use field::{
114 DetailCoefficients, EssentialCoefficients, FieldConfig, LegionField, LegionPattern, Resonance,
115};
116pub use orchestrator::{Orchestrator, TaskRouting};
117pub use quality::{FrequencyBand, QualityCurve, QualityMetrics, QualityTarget, SpectralFilter};
118pub use spectral_merge::{
119 BlendComponent, BlendStats, BlendedModel, DynamicBlendController, LayerDecomposition,
120 LayerType, LayerWeights, SpectralBlend, SpectralDecomposition, SpectralMergeError,
121};
122pub use speculative::{
123 DraftGenerator, DraftGeneratorConfig, DraftPool, DraftSequence,
124 QualityCurve as SpeculativeQualityCurve, RankedPath, SpeculativeLegion,
125 SpeculativeLegionConfig, SpeculativeStats, TokenId, VerificationResult, VerificationStats,
126};
127
128#[derive(Debug, Error)]
132pub enum LegionError {
133 #[error("No agents available for task")]
135 NoAgentsAvailable,
136
137 #[error("Cannot achieve quality {target}: max available {available}")]
139 InsufficientQuality {
140 target: f32,
142 available: f32,
144 },
145
146 #[error("Consensus failed: {0}")]
148 ConsensusFailed(String),
149
150 #[error("Agent error: {0}")]
152 Agent(String),
153
154 #[error("Operation timed out after {0:?}")]
156 Timeout(std::time::Duration),
157
158 #[error("Internal error: {0}")]
160 Internal(String),
161}
162
163pub type Result<T> = std::result::Result<T, LegionError>;
165
166#[derive(Debug, Clone)]
170pub struct LegionConfig {
171 pub agent_count: usize,
173 pub default_quality: f32,
175 pub progressive_refinement: bool,
177 pub consensus_strategy: ConsensusStrategy,
179 pub timeout: std::time::Duration,
181}
182
183impl Default for LegionConfig {
184 fn default() -> Self {
185 Self {
186 agent_count: 4,
187 default_quality: 0.8,
188 progressive_refinement: true,
189 consensus_strategy: ConsensusStrategy::WeightedMajority,
190 timeout: std::time::Duration::from_secs(30),
191 }
192 }
193}
194
195#[derive(Debug, Default)]
197pub struct LegionConfigBuilder {
198 agent_count: Option<usize>,
199 default_quality: Option<f32>,
200 progressive_refinement: Option<bool>,
201 consensus_strategy: Option<ConsensusStrategy>,
202 timeout: Option<std::time::Duration>,
203}
204
205impl LegionConfigBuilder {
206 pub fn with_agent_count(mut self, count: usize) -> Self {
208 self.agent_count = Some(count);
209 self
210 }
211
212 pub fn with_quality_target(mut self, quality: f32) -> Self {
214 self.default_quality = Some(quality);
215 self
216 }
217
218 pub fn with_progressive_refinement(mut self, enable: bool) -> Self {
220 self.progressive_refinement = Some(enable);
221 self
222 }
223
224 pub fn with_consensus_strategy(mut self, strategy: ConsensusStrategy) -> Self {
226 self.consensus_strategy = Some(strategy);
227 self
228 }
229
230 pub fn with_timeout(mut self, timeout: std::time::Duration) -> Self {
232 self.timeout = Some(timeout);
233 self
234 }
235
236 pub fn build(self) -> LegionConfig {
238 LegionConfig {
239 agent_count: self.agent_count.unwrap_or(4),
240 default_quality: self.default_quality.unwrap_or(0.8),
241 progressive_refinement: self.progressive_refinement.unwrap_or(true),
242 consensus_strategy: self
243 .consensus_strategy
244 .unwrap_or(ConsensusStrategy::WeightedMajority),
245 timeout: self.timeout.unwrap_or(std::time::Duration::from_secs(30)),
246 }
247 }
248}
249
250pub struct Legion {
254 config: LegionConfig,
255 agents: RwLock<Vec<Arc<LegionAgent>>>,
256 orchestrator: Arc<Orchestrator>,
257 context: Arc<SharedContext>,
258}
259
260impl Legion {
261 pub fn builder() -> LegionConfigBuilder {
263 LegionConfigBuilder::default()
264 }
265
266 pub fn new(config: LegionConfig) -> Result<Self> {
268 let context = Arc::new(SharedContext::new(config.agent_count));
269 let orchestrator = Arc::new(Orchestrator::new(config.clone()));
270
271 let mut agents = Vec::with_capacity(config.agent_count);
272 for i in 0..config.agent_count {
273 let agent_config = AgentConfig {
274 id: format!("legion-agent-{}", i),
275 frequency_band: FrequencyBand::from_index(i, config.agent_count),
276 context_fraction: (i + 1) as f32 / config.agent_count as f32,
277 };
278 agents.push(Arc::new(LegionAgent::new(agent_config)?));
279 }
280
281 Ok(Self {
282 config,
283 agents: RwLock::new(agents),
284 orchestrator,
285 context,
286 })
287 }
288
289 pub fn config(&self) -> &LegionConfig {
291 &self.config
292 }
293
294 pub fn agent_count(&self) -> usize {
296 self.agents.read().len()
297 }
298
299 pub fn context(&self) -> &Arc<SharedContext> {
301 &self.context
302 }
303
304 pub fn orchestrator(&self) -> &Arc<Orchestrator> {
306 &self.orchestrator
307 }
308}
309
310#[cfg(test)]
313mod integration_tests {
314 use super::*;
315
316 #[test]
317 fn test_legion_creation() {
318 let config = LegionConfig::default();
319 let legion = Legion::new(config);
320 assert!(legion.is_ok());
321
322 let legion = legion.expect("Failed to create legion");
323 assert_eq!(legion.agent_count(), 4);
324 }
325
326 #[test]
327 fn test_legion_builder() {
328 let config = Legion::builder()
329 .with_agent_count(8)
330 .with_quality_target(0.95)
331 .build();
332
333 assert_eq!(config.agent_count, 8);
334 assert!((config.default_quality - 0.95).abs() < 0.001);
335 }
336}