agent-migrate-adapters 0.6.1

Codex, Pi, and Claude Code configuration adapters for agent-migrate
Documentation
use std::path::{Path, PathBuf};

use agent_migrate_core::{AgentKind, BundleRelativePath, FileKind, Scope};
use serde::Serialize;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum ResourceClass {
    Migratable,
    MetadataOnly,
    Excluded,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct ResourceEntry {
    pub logical_path: String,
    pub class: ResourceClass,
    pub kind: Option<FileKind>,
    pub reason: String,
    pub bundle_path: Option<BundleRelativePath>,
    #[serde(skip)]
    source_path: Option<PathBuf>,
}

#[derive(Debug)]
pub(crate) struct MigratableLocation {
    pub logical: String,
    pub source: PathBuf,
    pub bundle: BundleRelativePath,
}

impl ResourceEntry {
    #[must_use]
    pub(crate) fn migratable(location: MigratableLocation, kind: FileKind) -> Self {
        Self {
            logical_path: location.logical,
            class: ResourceClass::Migratable,
            kind: Some(kind),
            reason: "supported adapter resource".to_owned(),
            bundle_path: Some(location.bundle),
            source_path: Some(location.source),
        }
    }

    #[must_use]
    pub(crate) fn protected(class: ResourceClass, index: usize, reason: &str) -> Self {
        Self {
            logical_path: format!("<redacted:{index}>"),
            class,
            kind: None,
            reason: reason.to_owned(),
            bundle_path: None,
            source_path: None,
        }
    }

    #[must_use]
    pub(crate) fn source_path(&self) -> Option<&Path> {
        self.source_path.as_deref()
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Inventory {
    pub agent: AgentKind,
    pub scope: Scope,
    pub entries: Vec<ResourceEntry>,
}

impl Inventory {
    #[must_use]
    pub const fn new(agent: AgentKind, scope: Scope, entries: Vec<ResourceEntry>) -> Self {
        Self {
            agent,
            scope,
            entries,
        }
    }

    #[must_use]
    pub fn count(&self, class: ResourceClass) -> usize {
        self.entries
            .iter()
            .filter(|entry| entry.class == class)
            .count()
    }
}