memorph 0.1.7

Convert, import, and export AI coding sessions between Claude Code, Codex, and OpenCode
use crate::model::{MemorphSession, SessionMeta};
use anyhow::Result;
use std::path::Path;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ProviderCapabilities {
    pub scan: bool,
    pub load: bool,
    pub write: bool,
    pub delete: bool,
    pub rename: bool,
    pub resume: bool,
}

impl ProviderCapabilities {
    pub const fn full_session_management() -> Self {
        Self {
            scan: true,
            load: true,
            write: true,
            delete: true,
            rename: true,
            resume: true,
        }
    }
}

impl Default for ProviderCapabilities {
    fn default() -> Self {
        Self {
            scan: true,
            load: true,
            write: false,
            delete: false,
            rename: false,
            resume: false,
        }
    }
}

/// Provider trait: each AI coding tool implements this interface
pub trait Provider: Send + Sync {
    fn id(&self) -> &'static str;
    fn name(&self) -> &'static str;
    fn capabilities(&self) -> ProviderCapabilities {
        ProviderCapabilities::default()
    }

    /// Scan all session metadata
    fn scan_sessions(&self) -> Result<Vec<SessionMeta>>;

    /// Load full messages for a given session
    fn load_session(&self, source_path: &str) -> Result<MemorphSession>;

    /// Write session to target tool directory (experimental)
    fn write_session(&self, session: &MemorphSession, target_dir: &Path) -> Result<String> {
        let _ = session;
        let _ = target_dir;
        anyhow::bail!("Write not supported for provider: {}", self.id())
    }

    /// Delete a session
    fn delete_session(&self, session_id: &str) -> Result<()> {
        let _ = session_id;
        anyhow::bail!("Delete not supported for provider: {}", self.id())
    }

    /// Rename a session
    fn rename_session(&self, session_id: &str, new_title: &str) -> Result<()> {
        let _ = session_id;
        let _ = new_title;
        anyhow::bail!("Rename not supported for provider: {}", self.id())
    }

    /// Build the provider-specific command used to resume a session.
    fn resume_command(&self, session_id: &str) -> Option<String> {
        let _ = session_id;
        None
    }

    /// Estimate the storage size (in bytes) of a single session.
    /// Default returns 0 (unknown).
    fn session_size(&self, session_id: &str) -> Result<u64> {
        let _ = session_id;
        Ok(0)
    }
}