illumitech-forge-cli 1.4.0

Evidence-backed agent execution CLI
Documentation
use std::{env, fs, path::Path};
fn walk(path: &Path, base: &Path, out: &mut String) {
    let mut entries: Vec<_> = fs::read_dir(path)
        .expect("read ui-dist")
        .map(|e| e.unwrap().path())
        .collect();
    entries.sort();
    for p in entries {
        assert!(
            !p.symlink_metadata().unwrap().file_type().is_symlink(),
            "no symlink assets"
        );
        if p.is_dir() {
            walk(&p, base, out);
        } else {
            let relative = p
                .strip_prefix(base)
                .unwrap()
                .to_str()
                .unwrap()
                .replace('\\', "/");
            let mime = match p.extension().and_then(|e| e.to_str()).unwrap_or("") {
                "html" => "text/html; charset=utf-8",
                "js" => "text/javascript; charset=utf-8",
                "css" => "text/css; charset=utf-8",
                "webp" => "image/webp",
                "svg" => "image/svg+xml",
                _ => "application/octet-stream",
            };
            out.push_str(&format!(
                "{key:?} => Some(({mime:?}, include_bytes!({file:?}))),\n",
                key = format!("/{relative}"),
                file = p.canonicalize().unwrap()
            ));
        }
    }
}
fn main() {
    let base = Path::new("ui-dist");
    println!("cargo:rerun-if-changed=ui-dist");
    for required in ["index.html", "logo.webp", "THIRD_PARTY_LICENSES.txt"] {
        assert!(
            base.join(required).is_file(),
            "required standalone UI asset missing: {required}; run the locked frontend build"
        );
    }
    let html = fs::read_to_string(base.join("index.html")).expect("read embedded UI entry point");
    for part in html.split('"').filter(|part| part.starts_with("/assets/")) {
        assert!(
            !part.contains("..") && base.join(&part[1..]).is_file(),
            "referenced embedded UI asset missing: {part}"
        );
    }
    let mut out = String::from(
        "fn asset(path: &str) -> Option<(&'static str, &'static [u8])> {match path {\n",
    );
    walk(base, base, &mut out);
    out.push_str("_ => None, }}");
    fs::write(
        Path::new(&env::var("OUT_DIR").unwrap()).join("workbench_assets.rs"),
        out,
    )
    .unwrap();
}