98 lines
3.0 KiB
Rust
98 lines
3.0 KiB
Rust
|
|
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<String>,
|
||
|
|
/// Sol gRPC endpoint (default: from sunbeam config)
|
||
|
|
#[arg(long)]
|
||
|
|
endpoint: Option<String>,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
pub async fn cmd_code(cmd: Option<CodeCommand>) -> 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<CodeCommand>) -> 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(())
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|