r2x 0.1.13

The r2x-cli plugin manager for model interoperability.
use crate::plugins::error::PluginError;
use r2x_config::Config;
use r2x_manifest::package_discovery::PackageLocator;
use r2x_manifest::types::Manifest;
use r2x_python::utils::resolve_site_package_path;
use std::path::PathBuf;

pub struct PluginContext {
    pub(crate) config: Config,
    pub(crate) manifest: Manifest,
    pub(crate) uv_path: String,
    pub(crate) venv_path: String,
    pub(crate) python_path: String,
    pub(crate) locator: PackageLocator,
}

impl PluginContext {
    pub fn load() -> Result<Self, PluginError> {
        let mut config = Config::load()
            .map_err(|e| PluginError::Config(format!("Failed to load config: {e}")))?;

        config
            .ensure_uv_path()
            .map_err(|e| PluginError::Config(format!("Failed to setup uv: {e}")))?;
        config
            .ensure_cache_path()
            .map_err(|e| PluginError::Config(format!("Failed to setup cache: {e}")))?;
        config
            .ensure_venv_path()
            .map_err(|e| PluginError::Config(format!("Failed to setup venv: {e}")))?;

        let uv_path = config
            .uv_path
            .clone()
            .ok_or_else(|| PluginError::Config("uv path not configured".to_string()))?;

        let venv_path = config.get_venv_path();
        let python_path = config.get_venv_python_path();

        let site_packages = resolve_site_package_path(&PathBuf::from(&venv_path))
            .map_err(|e| PluginError::Python(format!("Failed to resolve site-packages: {e}")))?;

        let locator = PackageLocator::new(site_packages).map_err(|e| {
            PluginError::Locator(format!("Failed to initialize package locator: {e}"))
        })?;

        let manifest = Manifest::load()?;

        Ok(PluginContext {
            config,
            manifest,
            uv_path,
            venv_path,
            python_path,
            locator,
        })
    }

    pub(crate) fn refresh_locator(&mut self) -> Result<(), PluginError> {
        self.locator
            .refresh()
            .map_err(|e| PluginError::Locator(format!("Failed to refresh package locator: {e}")))
    }
}