1mod codex;
2mod claude;
3mod zed;
4mod info;
5mod protocol;
6
7use serde::{Deserialize, Serialize};
8use crate::settings::Settings;
9
10pub use info::AppInfoProvider;
11
12pub use codex::CodexApp;
14pub use claude::ClaudeApp;
15pub use zed::ZedApp;
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
19pub enum SupportedApp {
20 CodexCLI,
22 ClaudeCode,
24 Zed,
26}
27
28impl SupportedApp {
29 pub fn from_str(s: &str) -> Option<Self> {
31 match s.to_lowercase().as_str() {
32 "codex-cli" | "codex" => Some(Self::CodexCLI),
33 "claude-code" | "claude" => Some(Self::ClaudeCode),
34 "zed-dev" | "zed" => Some(Self::Zed),
35 _ => None,
36 }
37 }
38
39 pub fn name(&self) -> &'static str {
41 match self {
42 Self::CodexCLI => "codex-cli",
43 Self::ClaudeCode => "claude-code",
44 Self::Zed => "zed",
45 }
46 }
47
48 pub fn all() -> Vec<Self> {
50 vec![
51 Self::CodexCLI,
52 Self::ClaudeCode,
53 Self::Zed,
54 ]
55 }
56}
57
58pub struct AppConfigGenerator;
60
61impl AppConfigGenerator {
62 pub fn generate_config(app: &SupportedApp, cli_api_key: Option<&str>) -> Settings {
64 match app {
65 SupportedApp::CodexCLI => CodexApp::generate_config(cli_api_key),
66 SupportedApp::ClaudeCode => ClaudeApp::generate_config(cli_api_key),
67 SupportedApp::Zed => ZedApp::generate_config(cli_api_key),
68 }
69 }
70
71 pub fn generate_protocol_config(protocols: &[String], cli_api_key: Option<&str>) -> Settings {
73 protocol::generate_protocol_config(protocols, cli_api_key)
74 }
75
76 pub(crate) fn resolve_env_var(template: &str, cli_api_key: Option<&str>) -> String {
78 if template.starts_with("${") && template.ends_with("}") {
79 let var_name = &template[2..template.len()-1];
80
81 if var_name == "LLM_LINK_API_KEY" {
83 if let Some(cli_key) = cli_api_key {
84 return cli_key.to_string();
85 }
86 }
87
88 std::env::var(var_name).unwrap_or_else(|_| {
90 eprintln!("Warning: Environment variable '{}' not found, using placeholder", var_name);
91 template.to_string()
92 })
93 } else {
94 template.to_string()
95 }
96 }
97}
98