mod ask;
mod ask_client;
mod ask_sources;
mod changes;
mod init;
mod inspect;
mod meta;
mod read;
mod recall;
mod related;
mod search;
pub(crate) mod secrets;
mod status;
mod sync;
use crate::cli::{Cli, Commands};
use crate::mcp::state::{ConfigState, McpServerState};
use crate::mcp::transport::run_jsonrpc_loop_with_state;
use crate::output::OutputMode;
use eyre::{Result, bail};
use std::io::{self, BufReader};
use std::sync::Arc;
pub async fn run(cli: &Cli) -> Result<()> {
if cli.skill {
use std::io::Write as _;
writeln!(io::stdout().lock(), "{}", crate::SKILL_MD)?;
return Ok(());
}
let Some(cmd) = &cli.command else {
bail!("missing command; try `talon --help`");
};
match cmd {
Commands::Mcp => {
crate::mcp::diagnostics::install_panic_hook();
let _ready_guard = crate::mcp::diagnostics::ready_guard();
let config = crate::config::load_config(cli.config_file.as_deref())?;
let vault_path = config.vault_path.clone();
let db_path = config.db_path.clone();
let config_path = config.config_file_path.clone();
let config_state = ConfigState {
config,
config_path,
vault_path,
db_path,
};
let state = McpServerState::new(config_state);
let vault_path_for_watcher = state.config.vault_path.clone();
crate::mcp::background::watcher::spawn_watcher(
vault_path_for_watcher,
Arc::clone(&state),
);
crate::mcp::background::embed::spawn_embed_ticker(Arc::clone(&state));
let stdin = io::stdin();
let stdout = io::stdout();
let outcome = tokio::task::block_in_place(|| {
run_jsonrpc_loop_with_state(BufReader::new(stdin.lock()), stdout.lock(), &state)
})?;
let _ = outcome;
crate::mcp::diagnostics::clear_ready();
Ok(())
}
Commands::Init(args) => init::emit(args),
Commands::Search(args) => search::emit(args, cli).await,
Commands::Ask(args) => ask::emit(args, cli).await,
Commands::Read(args) => read::emit(args, cli).await,
Commands::Sync(args) => sync::emit(args, cli).await,
Commands::Related(args) => related::emit(args, cli).await,
Commands::Status(args) => status::emit(args, cli),
Commands::Meta(args) => meta::emit(args, cli).await,
Commands::Changes(args) => changes::emit(args, cli).await,
Commands::Inspect(args) => inspect::emit(args, cli).await,
Commands::Recall(args) => recall::emit(args, cli).await,
Commands::Secrets(args) => secrets::emit(&args.subcommand),
}
}
pub(super) const fn output_mode(cli: &Cli) -> OutputMode {
if cli.agent {
OutputMode::Agent
} else if cli.json {
OutputMode::JsonPretty
} else {
OutputMode::Human
}
}
pub(super) fn should_spin(cli: &Cli) -> bool {
!cli.agent && !cli.json && crate::platform::stderr_is_tty()
}