use std::sync::{Arc, Mutex};
use async_trait::async_trait;
use lc_core::runnables::RunnableConfig;
use serde_json::Value;
use crate::AgentError;
mod fan_out_fan_in;
mod impls;
mod review;
mod sequential;
mod task_adapter;
#[cfg(test)]
mod tests;
pub use fan_out_fan_in::FanOutFanIn;
pub use review::{parse_review_verdict, review_envelope, ReviewOrchestrator, ReviewVerdict};
pub use sequential::SequentialPipeline;
pub use task_adapter::{task_adapter, TaskAdapter};
#[async_trait]
pub trait Orchestrator: Send + Sync {
type Input;
type Output;
async fn run_with_context(
&self,
input: Self::Input,
ctx: &RunContext,
) -> Result<Self::Output, AgentError>;
}
#[derive(Debug, Clone)]
pub struct RunContext {
pub trace_id: String,
pub shared_state: Option<Arc<Mutex<Value>>>,
}
pub fn generate_trace_id() -> String {
use std::time::{SystemTime, UNIX_EPOCH};
let nanos = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0);
format!("trace-{:x}", nanos)
}
impl RunContext {
pub fn new(trace_id: impl Into<String>) -> Self {
Self {
trace_id: trace_id.into(),
shared_state: None,
}
}
pub fn new_random() -> Self {
Self::new(generate_trace_id())
}
pub fn with_shared_state(mut self, shared_state: Arc<Mutex<Value>>) -> Self {
self.shared_state = Some(shared_state);
self
}
pub fn from_config(config: &RunnableConfig) -> Self {
let trace_id = config
.metadata
.get("trace_id")
.and_then(|v| v.as_str())
.map(|s| s.to_string())
.unwrap_or_else(generate_trace_id);
Self::new(trace_id)
}
}