use clap::{CommandFactory, Parser, Subcommand};
use clap_complete::{generate, Shell};
use octocode::config::Config;
use octocode::store::Store;
mod commands;
#[derive(Parser)]
#[command(name = "octocode")]
#[command(version = env!("CARGO_PKG_VERSION"))]
#[command(about = "Octocode is a smart code indexer and search tool")]
struct OctocodeArgs {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Index(commands::IndexArgs),
Search(commands::SearchArgs),
View(commands::ViewArgs),
Watch(commands::WatchArgs),
Config(commands::ConfigArgs),
#[command(name = "graphrag")]
GraphRAG(commands::GraphRAGArgs),
Mcp(commands::McpArgs),
#[command(name = "mcp-proxy")]
McpProxy(commands::McpProxyArgs),
Stats(commands::StatsArgs),
Explain(commands::ExplainArgs),
Diff(commands::DiffArgs),
Clear(commands::ClearArgs),
Commit(commands::CommitArgs),
Review(commands::ReviewArgs),
Release(commands::ReleaseArgs),
Format(commands::FormatArgs),
Logs(commands::LogsArgs),
Models {
#[command(subcommand)]
command: commands::ModelsCommand,
},
Completion {
#[arg(value_enum)]
shell: Shell,
},
}
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
dotenvy::dotenv().ok();
let args = OctocodeArgs::parse();
let config = Config::load()?;
if let Commands::Config(config_args) = &args.command {
return commands::config::execute(config_args, config);
}
if let Commands::Mcp(mcp_args) = &args.command {
return commands::mcp::run(mcp_args.clone()).await;
}
if let Commands::McpProxy(mcp_proxy_args) = &args.command {
return commands::mcp_proxy::run(mcp_proxy_args.clone()).await;
}
if let Commands::Commit(commit_args) = &args.command {
return commands::commit::execute(&config, commit_args).await;
}
if let Commands::Review(review_args) = &args.command {
return commands::review::execute(&config, review_args).await;
}
if let Commands::Release(release_args) = &args.command {
return commands::release::execute(&config, release_args).await;
}
if let Commands::Format(format_args) = &args.command {
return commands::format::execute(format_args).await;
}
if let Commands::Logs(logs_args) = &args.command {
return commands::logs::execute(logs_args).await;
}
if let Commands::Models { command } = &args.command {
return commands::models::execute_models_command(command.clone()).await;
}
if let Commands::Completion { shell } = &args.command {
let mut app = OctocodeArgs::command();
let name = app.get_name().to_string();
generate(*shell, &mut app, name, &mut std::io::stdout());
return Ok(());
}
let store = Store::new().await?;
store.initialize_collections().await?;
match &args.command {
Commands::Index(index_args) => {
commands::index::execute(&store, &config, index_args).await?
}
Commands::Search(search_args) => {
commands::search::execute(&store, search_args, &config).await?
}
Commands::View(view_args) => commands::view::execute(view_args).await?,
Commands::Watch(watch_args) => {
commands::watch::execute(&store, &config, watch_args).await?
}
Commands::GraphRAG(graphrag_args) => {
commands::graphrag::execute(&store, graphrag_args, &config).await?
}
Commands::Stats(stats_args) => {
commands::stats::execute(&store, stats_args, &config).await?
}
Commands::Explain(explain_args) => {
commands::explain::execute(&store, explain_args, &config).await?
}
Commands::Diff(diff_args) => commands::diff::execute(&store, diff_args, &config).await?,
Commands::Clear(clear_args) => commands::clear::execute(&store, clear_args).await?,
Commands::Config(_) => unreachable!(), Commands::Mcp(_) => unreachable!(), Commands::McpProxy(_) => unreachable!(), Commands::Commit(_) => unreachable!(), Commands::Review(_) => unreachable!(), Commands::Release(_) => unreachable!(), Commands::Format(_) => unreachable!(), Commands::Logs(_) => unreachable!(), Commands::Models { .. } => unreachable!(), Commands::Completion { .. } => unreachable!(), };
Ok(())
}