bot-forge 1.0.0

Rust CLI for installing agent skills and developer tools from configurable forms.
Documentation
use std::time::{Duration, Instant};

use bot_forge::config::{ConfigDocument, OriginMap};
use bot_forge::planning::{PlanRequest, TargetPlatform, build_plan};

#[test]
fn planning_scales_to_large_profiles_without_regression() {
    let tools = (0..5000)
        .map(|index| format!("tool-{index}"))
        .collect::<Vec<_>>();
    let mut source = format!(
        "catalog = \"rust-dev\"\n[profiles.smoke]\ncomponents = {:?}\n[profiles.standard]\n",
        tools
    );
    for name in &tools {
        source.push_str(&format!(
            "[[components]]\nid = \"{name}\"\nplatforms = [\"*\"]\n[components.detect]\nkind = \"command\"\nprogram = \"true\"\n[components.install]\nbackend = \"apt\"\npackages = [\"{name}\"]\n"
        ));
    }
    let config = ConfigDocument::parse(&source).unwrap();
    let started = Instant::now();
    let plan = build_plan(PlanRequest {
        document: &config,
        origins: &OriginMap::default(),
        profile: "smoke",
        target: TargetPlatform::host(),
        only: &[],
        exclude: &[],
        source_root: None,
    })
    .unwrap();
    assert_eq!(plan.components.len(), 5000);
    let budget = if cfg!(debug_assertions) {
        Duration::from_secs(1)
    } else {
        Duration::from_millis(250)
    };
    assert!(
        started.elapsed() < budget,
        "large-profile planning took {:?}",
        started.elapsed()
    );
}

#[test]
fn shorthand_expansion_and_planning_scale_without_external_work() {
    let tools = (0..5000)
        .map(|index| format!("cargo-tool-{index}"))
        .collect::<Vec<_>>();
    let mut source = format!(
        "catalog = \"rust-dev\"\n[profiles.smoke]\ncomponents = {:?}\n[profiles.standard]\n[cargo-tools]\n",
        tools
    );
    for name in &tools {
        source.push_str(&format!("{name} = \"=1.0.0\"\n"));
    }
    let started = Instant::now();
    let config = ConfigDocument::parse(&source).unwrap();
    let plan = build_plan(PlanRequest {
        document: &config,
        origins: &OriginMap::default(),
        profile: "smoke",
        target: TargetPlatform::host(),
        only: &[],
        exclude: &[],
        source_root: None,
    })
    .unwrap();
    assert_eq!(plan.components.len(), 5000);
    let budget = if cfg!(debug_assertions) {
        Duration::from_secs(2)
    } else {
        Duration::from_millis(500)
    };
    assert!(
        started.elapsed() < budget,
        "shorthand expansion and planning took {:?}",
        started.elapsed()
    );
}