Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 70 additions & 1 deletion crates/libsy/src/algorithms/vgr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,88 @@

#![allow(dead_code)]

use switchyard_protocol::Request;
use std::sync::Arc;

use switchyard_protocol::{ModelId, Request};

use self::text::ToolRecord;
use crate::Result;
use crate::algorithms::fall_through::FallThrough;
use crate::algorithms::util::affinity::AffinityRouter;
use crate::core::algorithm::{Algorithm, Driver, RoutingOutcome};
use crate::core::state::State;

mod config;
mod decide;
mod readout;
mod render;
mod rungs;
mod runtime;
mod safety;
mod text;

pub use config::{ACTIVE_APPROVAL, ServingMode, Targets, VgrConfig};
pub use safety::{BreakerConfig, KillSwitch};

#[cfg(test)]
mod tests;

/// A verification-gated route between a local and a capable tier.
pub struct Vgr {
route: FallThrough<State>,
local: ModelId,
cloud: ModelId,
}

impl Vgr {
/// Validates and constructs a verification-gated route.
pub fn new(config: VgrConfig) -> Result<Self> {
config.validate()?;
let local = config.targets.local.clone();
let cloud = config.targets.cloud.clone();
// Every local turn re-enters verification; an escalation holds until the
// next user turn.
let turn_affinity = Arc::new(
AffinityRouter::new()
.with_release_on_user_turn()
.with_latch_only([cloud.clone()]),
);
let classifier = Arc::new(runtime::VgrClassifier {
breaker: safety::CircuitBreaker::new(config.breaker),
config,
});
let route = FallThrough::new_with_state()
.with_name("vgr")
.with_processor(turn_affinity.clone())
.with_classifier(turn_affinity)
.with_classifier(classifier);
Ok(Self {
route,
local,
cloud,
})
}
}

#[async_trait::async_trait]
impl Algorithm for Vgr {
fn name(&self) -> &str {
"vgr"
}

async fn route(self: Arc<Self>, driver: Driver, request: Request) -> Result<RoutingOutcome> {
let mut outcome = self.route.execute(driver, request).await?;
let selected = outcome.selected_model_id()?.clone();
if selected == self.cloud {
// Falling back to local would bypass the decision that selected cloud.
outcome.selected_model_ids.truncate(1);
} else if selected == self.local && outcome.response.is_none() {
outcome.selected_model_ids = vec![self.local.clone(), self.cloud.clone()];
}
Ok(outcome)
}
}

/// The verification regime a request's capabilities license.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
enum Branch {
Expand Down
112 changes: 112 additions & 0 deletions crates/libsy/src/algorithms/vgr/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

use std::time::Duration;

use switchyard_protocol::ModelId;

use super::safety::{BreakerConfig, KillSwitch};
use crate::{LibsyError, Result};

/// Required attestation for live local commits.
pub const ACTIVE_APPROVAL: &str = "prospective-validation-and-canary-approved";

/// Authority granted to VGR decisions.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub enum ServingMode {
/// Always serves cloud without producing an attempt.
#[default]
Off,
/// Serves decisions, for isolated measurement.
Evaluate,
/// Decides but always serves cloud.
Shadow,
/// Serves decisions after operator approval.
Active {
/// Operator approval attestation.
approval: String,
},
}

/// Targets used by a VGR route.
#[derive(Clone, Debug)]
pub struct Targets {
/// Tier that produces the candidate attempt.
pub local: ModelId,
/// Tier used when the candidate is not licensed.
pub cloud: ModelId,
/// Local verifier, defaulting to `local`.
pub judge: Option<ModelId>,
/// Capable-tier verifier; unset removes the cloud confirmation rungs.
pub cloud_judge: Option<ModelId>,
}

/// VGR runtime configuration.
#[derive(Clone, Debug)]
pub struct VgrConfig {
/// Completion and verifier targets.
pub targets: Targets,
/// Authority granted to routing decisions.
pub mode: ServingMode,
/// Budget for one turn's attempt and verification.
pub deadline: Duration,
/// Optional live stop controlled by the operator.
pub kill_switch: Option<KillSwitch>,
/// Local endpoint breaker tuning.
pub breaker: BreakerConfig,
/// Whether a cheap typing call selects a verification regime.
pub task_typing: bool,
/// Whether the local tier accepts image content.
pub local_supports_images: bool,
/// Lets a long agentic run with earlier tool errors commit on a capable-tier
/// confirmation once it ends in this many consecutive clean tool results.
pub confirmed_recovery_min_clean_tail: Option<u32>,
}

impl VgrConfig {
/// Creates an off-by-default route between local and capable tiers.
pub fn new(local: ModelId, cloud: ModelId) -> Self {
Self {
targets: Targets {
local,
cloud,
judge: None,
cloud_judge: None,
},
mode: ServingMode::Off,
deadline: Duration::from_secs(30),
kill_switch: None,
breaker: BreakerConfig::default(),
task_typing: true,
local_supports_images: false,
confirmed_recovery_min_clean_tail: None,
}
}

pub(super) fn validate(&self) -> Result<()> {
if self.deadline.is_zero() || self.breaker.threshold == 0 {
return Err(LibsyError::AlgorithmError {
message: "vgr deadline and breaker threshold must be non-zero".into(),
});
}
if let ServingMode::Active { approval } = &self.mode
&& approval != ACTIVE_APPROVAL
{
return Err(LibsyError::AlgorithmError {
message: format!(
"vgr active mode requires approval attestation {ACTIVE_APPROVAL:?}"
),
});
}
Ok(())
}

pub(super) fn judge(&self) -> &ModelId {
self.targets.judge.as_ref().unwrap_or(&self.targets.local)
}

pub(super) fn confirmed_min_clean_tail(&self) -> Option<i32> {
self.confirmed_recovery_min_clean_tail
.map(|tail| i32::try_from(tail.max(1)).unwrap_or(i32::MAX))
}
}
Loading
Loading