use crate::traits::SpecialistKind;
use std::path::PathBuf;
use std::sync::Arc;
mod parse;
mod registry;
mod render;
pub mod validation;
#[cfg(test)]
mod equivalence_tests;
#[cfg(test)]
mod override_tests;
#[allow(unused_imports)]
pub use parse::parse_specialist;
#[allow(unused_imports)]
pub use render::render_template;
#[derive(Debug, Default, Clone)]
pub struct SpecialistRenderContext {
pub mission: String,
pub task: String,
pub depth: usize,
pub max_depth: usize,
pub max_iterations: usize,
pub goal_id: String,
pub working_dir: String,
pub is_scheduled: bool,
pub parent_session_id: String,
pub execution_mode: String,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct SpecialistDef {
pub kind: SpecialistKind,
pub description: String,
pub system_prompt_template: String,
pub model: Option<String>,
pub tools: Option<Vec<String>>,
pub max_iterations: Option<usize>,
pub tool_budget: Option<usize>,
pub timeout_secs: Option<u64>,
pub source: SpecialistSource,
}
#[derive(Debug, Clone)]
pub enum SpecialistSource {
Bundled,
UserOverride(#[allow(dead_code)] PathBuf),
}
#[derive(Debug, Default)]
pub struct SpecialistRegistry {
by_kind: std::collections::HashMap<SpecialistKind, Arc<SpecialistDef>>,
}
impl SpecialistRegistry {
pub fn llm_visible_kinds(&self) -> Vec<(&'static str, String)> {
let mut out: Vec<(&'static str, String)> = SpecialistKind::all()
.iter()
.filter(|k| **k != SpecialistKind::TaskLead)
.filter_map(|k| {
self.by_kind
.get(k)
.map(|def| (k.as_str(), def.description.clone()))
})
.collect();
out.sort_by_key(|(name, _)| *name);
out
}
}