mod claude;
mod cli_transport;
mod codebuddy;
pub(crate) mod codex;
mod host_tools;
mod protocol;
use a3s_code_core::llm::LlmClient;
use anyhow::Result;
use std::sync::Arc;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) enum AccountProvider {
Claude,
Codex,
CodeBuddy,
}
impl AccountProvider {
pub(crate) const ALL: [Self; 3] = [Self::Claude, Self::Codex, Self::CodeBuddy];
pub(crate) const fn label(self) -> &'static str {
match self {
Self::Claude => "Claude Code",
Self::Codex => "Codex",
Self::CodeBuddy => "WorkBuddy",
}
}
pub(crate) fn is_available(self) -> bool {
match self {
Self::Claude => claude::has_claude_login(),
Self::Codex => codex::has_valid_codex_login(),
Self::CodeBuddy => codebuddy::has_workbuddy_login(),
}
}
pub(crate) fn local_models(self) -> Vec<String> {
match self {
Self::Claude => claude::models(),
Self::Codex => codex::cached_codex_models()
.into_iter()
.map(|model| model.slug)
.collect(),
Self::CodeBuddy => codebuddy::fallback_models(),
}
}
pub(crate) async fn discover_models(self) -> Result<Vec<String>> {
match self {
Self::Claude => Ok(self.local_models()),
Self::Codex => Ok(codex::refresh_codex_models()
.await?
.into_iter()
.map(|model| model.slug)
.collect()),
Self::CodeBuddy => codebuddy::discover_models().await,
}
}
pub(crate) fn canonical_model(self, model: &str) -> String {
match self {
Self::Claude => claude::canonical_model_name(model),
Self::Codex | Self::CodeBuddy => model.trim().to_string(),
}
}
pub(crate) fn client(self, model: &str, session_id: &str) -> Result<Arc<dyn LlmClient>> {
let model = self.canonical_model(model);
match self {
Self::Claude => Ok(Arc::new(claude::ClaudeClient::from_claude_login(&model)?)),
Self::Codex => Ok(Arc::new(codex::CodexClient::from_codex_login(
&model, session_id,
)?)),
Self::CodeBuddy => Ok(Arc::new(codebuddy::CodeBuddyClient::from_workbuddy_login(
&model,
)?)),
}
}
pub(crate) fn model_context(self, model: &str) -> Option<u32> {
match self {
Self::Codex => codex::codex_model_context(model),
Self::Claude | Self::CodeBuddy => None,
}
}
}