use super::inline::{InlineExecutor, InlineRegistry};
use super::nix::NixExecutor;
use super::runtime::RuntimeExecutor;
use super::{ExecutionError, StageExecutor};
use noether_core::stage::StageId;
use noether_store::StageStore;
use serde_json::Value;
pub struct CompositeExecutor {
inline: InlineExecutor,
nix: Option<NixExecutor>,
runtime: RuntimeExecutor,
}
impl CompositeExecutor {
pub fn from_store(store: &dyn StageStore) -> Self {
Self::from_store_with_registry(store, InlineRegistry::new())
}
pub fn from_store_with_registry(store: &dyn StageStore, registry: InlineRegistry) -> Self {
let inline = InlineExecutor::from_store_with_registry(store, registry);
let nix = NixExecutor::from_store(store);
let runtime = RuntimeExecutor::from_store(store);
if nix.is_some() {
eprintln!("Nix executor: active (synthesized stages will run via nix)");
}
Self {
inline,
nix,
runtime,
}
}
pub fn with_llm(
mut self,
llm: Box<dyn crate::llm::LlmProvider>,
config: crate::llm::LlmConfig,
) -> Self {
self.runtime.set_llm(llm, config);
self
}
pub fn with_embedding(
mut self,
provider: Box<dyn crate::index::embedding::EmbeddingProvider>,
) -> Self {
self.runtime = self.runtime.with_embedding(provider);
self
}
pub fn register_synthesized(&mut self, stage_id: &StageId, code: &str, language: &str) {
if let Some(nix) = &mut self.nix {
nix.register(stage_id, code, language);
}
}
pub fn nix_available(&self) -> bool {
self.nix.is_some()
}
}
impl StageExecutor for CompositeExecutor {
fn execute(&self, stage_id: &StageId, input: &Value) -> Result<Value, ExecutionError> {
if let Some(nix) = &self.nix {
if nix.has_implementation(stage_id) {
return nix.execute(stage_id, input);
}
}
if self.runtime.has_implementation(stage_id) {
return self.runtime.execute(stage_id, input);
}
self.inline.execute(stage_id, input)
}
}