pub mod client; pub mod config; pub mod project; pub mod tools; use clap::Subcommand; use tracing::info; #[derive(Subcommand, Debug)] pub enum CodeCommand { /// Start a coding session (default — can omit subcommand) Start { /// Model override (e.g., devstral-2) #[arg(long)] model: Option, /// Sol gRPC endpoint (default: from sunbeam config) #[arg(long)] endpoint: Option, }, } pub async fn cmd_code(cmd: Option) -> sunbeam_sdk::error::Result<()> { cmd_code_inner(cmd).await.map_err(|e| sunbeam_sdk::error::SunbeamError::Other(e.to_string())) } async fn cmd_code_inner(cmd: Option) -> anyhow::Result<()> { let cmd = cmd.unwrap_or(CodeCommand::Start { model: None, endpoint: None, }); match cmd { CodeCommand::Start { model, endpoint } => { let endpoint = endpoint.unwrap_or_else(|| "http://127.0.0.1:50051".into()); // Discover project context let project = project::discover_project(".")?; info!( project = project.name.as_str(), path = project.path.as_str(), branch = project.git_branch.as_deref().unwrap_or("?"), "Discovered project" ); // Load project config let cfg = config::load_project_config(&project.path); let model = model .or(cfg.model_name.clone()) .unwrap_or_else(|| "devstral-small-2506".into()); // Connect to Sol let mut session = client::connect(&endpoint, &project, &cfg, &model).await?; info!( session_id = session.session_id.as_str(), room_id = session.room_id.as_str(), model = session.model.as_str(), "Connected to Sol" ); // For now, simple stdin loop (ratatui TUI in Phase 4) println!("sunbeam code · {} · {}", project.name, model); println!("connected to Sol (session: {})", &session.session_id[..8]); println!("type a message, /quit to exit\n"); let stdin = tokio::io::stdin(); let reader = tokio::io::BufReader::new(stdin); use tokio::io::AsyncBufReadExt; let mut lines = reader.lines(); while let Ok(Some(line)) = lines.next_line().await { let line = line.trim().to_string(); if line.is_empty() { continue; } if line == "/quit" { session.end().await?; println!("session ended."); break; } print!("> "); match session.chat(&line).await { Ok(response) => { println!("\n{}\n", response); } Err(e) => { eprintln!("error: {e}"); } } } Ok(()) } } }