Skip to main content

switchyard_runner/
algorithm_factory.rs

1// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Algorithm construction from deployment TOML without provider clients.
5
6use std::collections::BTreeMap;
7use std::sync::Arc;
8
9use libsy::{Algorithm, RuntimeModels};
10
11use crate::RunnerError;
12use crate::config::DeploymentConfig;
13
14pub(crate) type AlgorithmAndModels = (Arc<dyn Algorithm>, RuntimeModels);
15
16/// Parsed deployment configuration for building algorithms with host-owned execution.
17pub struct AlgorithmFactory {
18    pub(crate) config: DeploymentConfig,
19}
20
21impl AlgorithmFactory {
22    /// Parses deployment TOML without resolving credentials or constructing provider clients.
23    /// Invalid TOML returns a configuration error; routing settings are checked by [`Self::build`].
24    pub fn from_toml(source: &str) -> Result<Self, RunnerError> {
25        let mut config: DeploymentConfig = toml::from_str(source).map_err(|error| {
26            RunnerError::configuration_source(format!("failed to parse TOML: {error}"), error)
27        })?;
28        config.infer_decision_judges();
29        Ok(Self { config })
30    }
31
32    /// Builds algorithms and their model groups, keyed by configured route `id`.
33    ///
34    /// LLM calls and outcomes use target names; the host resolves their provider IDs and
35    /// owns target prompts, provider settings and transport. Decision calls use provider IDs.
36    /// Reuse the returned algorithms across requests to retain algorithm-owned state.
37    pub fn build(&self) -> Result<BTreeMap<String, AlgorithmAndModels>, RunnerError> {
38        self.config.validate()?;
39        if self.config.requires_target_admission() {
40            return Err(RunnerError::configuration(
41                "target eligibility requires Runner admission; use Runner instead of AlgorithmFactory",
42            ));
43        }
44        self.config
45            .build_algorithms()
46            .map(|entry| {
47                let (_, config, algorithm) = entry?;
48                Ok((config.id.to_string(), algorithm))
49            })
50            .collect()
51    }
52}