Skip to main content

zeroclaw_runtime/skills/
bundle.rs

1//! Runtime-side bundle facade. The directory rules (default path, inside-
2//! `shared/` containment, uniqueness) live in [`zeroclaw_config::skill_bundles`]
3//! so `Config::validate` and the SkillsService share one implementation.
4//! This module is a thin re-exporter plus the `BundleSummary` shape
5//! returned to surface callers.
6
7use std::path::{Path, PathBuf};
8
9use zeroclaw_config::schema::Config;
10pub use zeroclaw_config::skill_bundles::{
11    BundleDirectoryError as BundleError, default_directory, resolve_directory, validate_directory,
12    validate_uniqueness,
13};
14
15/// Lightweight bundle view returned by [`crate::skills::service::SkillsService::list_bundles`].
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct BundleSummary {
18    pub alias: String,
19    pub directory: PathBuf,
20    pub include: Vec<String>,
21    pub exclude: Vec<String>,
22}
23
24/// Build a [`BundleSummary`] for a configured bundle alias. Resolves the
25/// directory via [`resolve_directory`] so default-path behaviour stays
26/// single-sourced.
27pub fn summary(
28    config: &Config,
29    install_root: &Path,
30    alias: &str,
31) -> Result<BundleSummary, BundleError> {
32    let bundle = config
33        .skill_bundles
34        .get(alias)
35        .ok_or_else(|| BundleError::UnknownBundle(alias.to_string()))?;
36    Ok(BundleSummary {
37        alias: alias.to_string(),
38        directory: resolve_directory(config, install_root, alias)?,
39        include: bundle.include.clone(),
40        exclude: bundle.exclude.clone(),
41    })
42}