use clap::Subcommand;
use tail_fin_common::TailFinError;
use crate::session::{print_json, Ctx};
#[derive(Subcommand)]
pub enum GrokAction {
Ask {
prompt: String,
#[arg(long, default_value_t = 30)]
timeout: u64,
},
Conversations,
}
pub async fn run(action: GrokAction, ctx: &Ctx) -> Result<(), TailFinError> {
if ctx.cookies.is_some() {
eprintln!("Error: Grok requires browser mode (Cloudflare protection).");
eprintln!(" (Connects to Chrome at 127.0.0.1:9222 by default)");
std::process::exit(1);
}
let chrome_host = ctx.connect.as_deref().unwrap_or("127.0.0.1:9222");
let session = crate::session::browser_session(chrome_host, ctx.headed).await?;
let client = tail_fin_grok::GrokClient::new(session);
match action {
GrokAction::Ask { prompt, timeout } => {
let resp = client.ask(&prompt, timeout).await?;
print_json(&serde_json::json!({
"response": resp.response,
"conversation_id": resp.conversation_id,
}))?;
}
GrokAction::Conversations => {
let convs = client.list_conversations().await?;
print_json(&serde_json::json!({
"conversations": convs,
}))?;
}
}
Ok(())
}
pub struct Adapter;
impl crate::adapter::CliAdapter for Adapter {
fn name(&self) -> &'static str {
"grok"
}
fn about(&self) -> &'static str {
"Grok AI operations"
}
fn command(&self) -> clap::Command {
<GrokAction as clap::Subcommand>::augment_subcommands(
clap::Command::new("grok").about("Grok AI operations"),
)
}
fn dispatch<'a>(
&'a self,
matches: &'a clap::ArgMatches,
ctx: &'a crate::session::Ctx,
) -> std::pin::Pin<
Box<
dyn std::future::Future<Output = Result<(), tail_fin_common::TailFinError>> + Send + 'a,
>,
> {
Box::pin(async move {
let action = <GrokAction as clap::FromArgMatches>::from_arg_matches(matches)
.map_err(|e| tail_fin_common::TailFinError::Api(e.to_string()))?;
run(action, ctx).await
})
}
}