use clap::{Parser,Subcommand,CommandFactory};
use reedline::{Prompt,Reedline,Signal,PromptHistorySearch,PromptEditMode};
use std::borrow::Cow;
use tokio::runtime::Runtime;
use std::env;
use nexgenomics::utils::{get_api_auth_token,set_api_auth_token};
use nexgenomics::threads;
#[derive(Parser,Debug)]
#[command(name="nexgenomics")]
#[command(version)]
#[command(about="This is the NexGenomics CLI\nCopyright(C) 2026 by NexGenomics Inc.\nAll Rights Reserved\n",long_about=None)]
struct Cli {
#[command(subcommand)]
command:Commands,
}
#[derive(Subcommand,Debug)]
enum Commands {
Hello {
#[arg(short,long)]
name:Option<String>
},
Version,
Quit,
Exit,
Thread,
#[command(alias="?")]
Commands,
#[command(subcommand)]
Create(Creates),
#[command(about=r#"
**set-auth-token** prompts you for an authentication token, which is
required for various tasks in this command-line utility and in the
NexGenomics REST API.
You must enter the auth token via the prompt. There's no command-line
option that takes it. This enhances security.
Go to https://agentstore.nexgenomics.ai to create an auth token.
The token will be stored on your system at $HOME/.nexgenomicsrc.
"#)]
SetAuthToken(SetAuthTokenArgs),
}
#[derive(Subcommand,Debug)]
enum Creates {
DataConnector {
}
}
#[derive(Parser,Debug)]
struct SetAuthTokenArgs {
#[arg(trailing_var_arg=true)]
args:Vec<String>,
}
struct MyPrompt;
impl Prompt for MyPrompt {
fn render_prompt_left(&self) -> Cow<'_,str> {
Cow::Borrowed("NG> ")
}
fn render_prompt_right(&self) -> Cow<'_,str> {
Cow::Borrowed("")
}
fn render_prompt_indicator(&self, _prompt_mode: PromptEditMode) -> Cow<'_,str> {
Cow::Borrowed("")
}
fn render_prompt_multiline_indicator(&self) -> Cow<'_,str> {
Cow::Borrowed("::: ")
}
fn render_prompt_history_search_indicator(
&self,
_history_search: PromptHistorySearch,
) -> Cow<'_,str> {
Cow::Borrowed("⏳ ")
}
}
fn main() {
let args:Vec<String> = env::args().collect();
if args.len() > 1 {
if args[1] == "unittest" {
println!("That's a unit test, son.");
return;
} else if args[1] == "thread" {
let rt = Runtime::new().unwrap();
match rt.block_on(threads::run_generic_chatbot()) {
Ok(_) => println!("Done"),
Err(e) => eprintln!("{}",e),
}
return;
}
}
let mut line_editor = Reedline::create();
let prompt = MyPrompt;
println!("NexGenomics Shell");
loop {
match line_editor.read_line(&prompt) {
Ok(Signal::Success(line)) => {
let input = line.trim();
let args = std::iter::once("").chain(input.split_whitespace());
match Cli::try_parse_from(args) {
Ok(cli) => {
match cli.command {
Commands::Quit => {
break;
}
Commands::Version => {
let v = env!("CARGO_PKG_VERSION");
println!("{}", v);
}
Commands::Exit => {
break;
}
Commands::Commands => {
let mut c = Cli::command();
let _ = c.print_help();
println!();
}
Commands::SetAuthToken(run_args) => set_auth_token(run_args),
Commands::Thread => {
let rt = Runtime::new().unwrap();
let _ = rt.block_on(threads::run_generic_chatbot());
},
_ => {}
}
}
Err(e) => {
eprintln!("{}",e);
}
}
}
Ok(Signal::CtrlC) | Ok(Signal::CtrlD) => {
break;
}
Err(_err) => {
break;
}
}
}
}
fn set_auth_token(run_args: SetAuthTokenArgs) {
if let Some(token) = get_api_auth_token() {
println!("Token already exists {}", token);
return;
}
if let Some(token) = run_args.args.first() {
match set_api_auth_token(token) {
Ok(()) => println!("✅ Ok"),
Err(err) => eprintln!("❌ Didn't work, {}", err),
}
} else {
println!("❌ No token specified!");
}
}