regy 0.1.0

Private-by-default desktop agent for the Regy web interface
use crate::{
    config::app::ProviderId,
    dependencies::pi::{ANTIGRAVITY_EXTENSION, CLAUDE_AUTH_EXTENSION, PiPackageSource},
};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct ExtensionRequirement {
    pub(crate) package: PiPackageSource,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum LoginAction {
    InheritedCommand {
        program: &'static str,
        args: &'static [&'static str],
    },
    InteractivePi {
        instruction: &'static str,
    },
}

pub(crate) struct ProviderDescriptor {
    // Kept with each static descriptor so configuration validation can address the provider by ID.
    #[allow(dead_code)]
    pub(crate) id: ProviderId,
    pub(crate) display_name: &'static str,
    pub(crate) pi_provider: &'static str,
    pub(crate) executable: Option<&'static str>,
    pub(crate) extension: Option<ExtensionRequirement>,
    pub(crate) login: &'static [LoginAction],
    pub(crate) setup_steps: &'static [&'static str],
}

const CODEX_LOGIN: &[LoginAction] = &[LoginAction::InteractivePi {
    instruction: "Run /login openai-codex, finish the browser flow, then exit Pi.",
}];
const CLAUDE_LOGIN: &[LoginAction] = &[
    LoginAction::InheritedCommand {
        program: "claude",
        args: &["auth", "login"],
    },
    LoginAction::InteractivePi {
        instruction: "Run /login claude-code, finish, then exit Pi.",
    },
];
const ANTIGRAVITY_LOGIN: &[LoginAction] = &[LoginAction::InteractivePi {
    instruction: "Run /login antigravity, finish, then exit Pi.",
}];

const CODEX_SETUP_STEPS: &[&str] =
    &["Run /login openai-codex, finish the browser flow, then exit Pi."];
const CLAUDE_SETUP_STEPS: &[&str] =
    &["Run `claude auth login`, then run /login claude-code in Pi and exit Pi."];
const ANTIGRAVITY_SETUP_STEPS: &[&str] = &["Run /login antigravity, finish, then exit Pi."];

pub(crate) fn descriptor(id: ProviderId) -> ProviderDescriptor {
    match id {
        ProviderId::OpenaiCodex => ProviderDescriptor {
            id,
            display_name: "OpenAI Codex",
            pi_provider: "openai-codex",
            executable: None,
            extension: None,
            login: CODEX_LOGIN,
            setup_steps: CODEX_SETUP_STEPS,
        },
        ProviderId::ClaudeCode => ProviderDescriptor {
            id,
            display_name: "Claude Code",
            pi_provider: "claude-code",
            executable: Some("claude"),
            extension: Some(ExtensionRequirement {
                package: CLAUDE_AUTH_EXTENSION,
            }),
            login: CLAUDE_LOGIN,
            setup_steps: CLAUDE_SETUP_STEPS,
        },
        ProviderId::Antigravity => ProviderDescriptor {
            id,
            display_name: "Antigravity",
            pi_provider: "antigravity",
            executable: None,
            extension: Some(ExtensionRequirement {
                package: ANTIGRAVITY_EXTENSION,
            }),
            login: ANTIGRAVITY_LOGIN,
            setup_steps: ANTIGRAVITY_SETUP_STEPS,
        },
    }
}