use crate::errors::CliError;
use crate::git;
use crate::output::format::OutputFormat;
use std::fs;
use std::io::IsTerminal;
pub fn run(
target_file: Option<String>,
eval_command: Option<String>,
metric_name: &str,
metric_direction: &str,
time_budget: &str,
branch: &str,
json: bool,
) -> Result<(), CliError> {
let format = OutputFormat::detect(json);
if !git::is_git_repo() {
return Err(CliError::NotGitRepo);
}
if std::path::Path::new("autoresearch.toml").exists() {
match format {
OutputFormat::Json => {
println!(
"{}",
serde_json::json!({
"status": "already_initialized",
"message": "autoresearch.toml already exists"
})
);
}
OutputFormat::Table => {
println!("autoresearch.toml already exists. Edit it directly to change settings.");
}
}
return Ok(());
}
let is_interactive = std::io::stdin().is_terminal() && target_file.is_none();
let (target_file, eval_command) = if is_interactive {
use dialoguer::{Input, Select};
let tf: String = Input::new()
.with_prompt("Target file (the single file the agent may modify)")
.interact_text()
.map_err(|e| CliError::Config(e.to_string()))?;
let ec: String = Input::new()
.with_prompt("Eval command (produces the metric)")
.interact_text()
.map_err(|e| CliError::Config(e.to_string()))?;
let _metric_name_input: String = Input::new()
.with_prompt("Metric name")
.default(metric_name.to_string())
.interact_text()
.map_err(|e| CliError::Config(e.to_string()))?;
let directions = &["lower is better", "higher is better"];
let _direction_idx = Select::new()
.with_prompt("Metric direction")
.items(directions)
.default(0)
.interact()
.map_err(|e| CliError::Config(e.to_string()))?;
(tf, ec)
} else {
let tf = target_file.ok_or_else(|| {
CliError::Config(
"In non-interactive mode, --target-file is required. \
Example: autoresearch init --target-file train.py --eval-command 'python train.py'"
.to_string(),
)
})?;
let ec = eval_command.ok_or_else(|| {
CliError::Config(
"In non-interactive mode, --eval-command is required. \
Example: autoresearch init --target-file train.py --eval-command 'python train.py'"
.to_string(),
)
})?;
(tf, ec)
};
let mut config_table = toml::map::Map::new();
config_table.insert(
"target_file".to_string(),
toml::Value::String(target_file.clone()),
);
config_table.insert(
"eval_command".to_string(),
toml::Value::String(eval_command.clone()),
);
config_table.insert(
"metric_name".to_string(),
toml::Value::String(metric_name.to_string()),
);
config_table.insert(
"metric_direction".to_string(),
toml::Value::String(metric_direction.to_string()),
);
config_table.insert(
"time_budget".to_string(),
toml::Value::String(time_budget.to_string()),
);
config_table.insert(
"branch".to_string(),
toml::Value::String(branch.to_string()),
);
let config_str = format!(
"# Autoresearch configuration\n# Generated by autoresearch CLI v{}\n\n{}",
env!("CARGO_PKG_VERSION"),
toml::to_string_pretty(&toml::Value::Table(config_table))
.map_err(|e| CliError::Config(e.to_string()))?
);
fs::write("autoresearch.toml", &config_str)?;
fs::create_dir_all(".autoresearch")?;
if !std::path::Path::new("program.md").exists() {
let program = format!(
"# Autoresearch Program\n\n\
## Goal\n\
Optimize `{metric_name}` ({metric_direction} is better) by modifying `{target_file}`.\n\n\
## Ideas to Explore\n\
<!-- Add your research directions, ideas, and hypotheses here. -->\n\n\
1.\n\n\
## Constraints\n\
- Time budget per experiment: {time_budget}\n\
- Only modify: {target_file}\n\
- Eval command: `{eval_command}`\n",
);
fs::write("program.md", &program)?;
}
match format {
OutputFormat::Json => {
println!(
"{}",
serde_json::json!({
"status": "success",
"files_created": ["autoresearch.toml", "program.md", ".autoresearch/"],
"config": {
"target_file": target_file,
"eval_command": eval_command,
"metric_name": metric_name,
"metric_direction": metric_direction,
"time_budget": time_budget,
"branch": branch,
}
})
);
}
OutputFormat::Table => {
println!();
println!("Initialized autoresearch project:");
println!(" autoresearch.toml — experiment configuration");
println!(" program.md — research direction & ideas (edit this!)");
println!(" .autoresearch/ — experiment logs");
println!();
println!(
"Next: edit program.md with your ideas, then tell your agent to run /autoresearch"
);
}
}
Ok(())
}