use clap::{Args, Subcommand};
use colored::Colorize;
#[derive(Subcommand)]
pub enum SessionCommands {
List(ListArgs),
Create(CreateArgs),
Get(GetArgs),
Delete(DeleteArgs),
Send(SendArgs),
Chat(ChatArgs),
}
#[derive(Args)]
pub struct ListArgs {
pub agent: String,
}
#[derive(Args)]
pub struct CreateArgs {
pub agent: String,
}
#[derive(Args)]
pub struct GetArgs {
pub agent: String,
pub session_id: String,
}
#[derive(Args)]
pub struct DeleteArgs {
pub agent: String,
pub session_id: String,
#[arg(long)]
pub force: bool,
}
#[derive(Args)]
pub struct SendArgs {
pub agent: String,
pub session_id: String,
#[arg(long, short)]
pub message: String,
#[arg(long)]
pub thinking: bool,
}
#[derive(Args)]
pub struct ChatArgs {
pub agent: String,
pub session_id: Option<String>,
#[arg(long)]
pub thinking: bool,
}
pub async fn execute(cmd: SessionCommands) -> anyhow::Result<()> {
match cmd {
SessionCommands::List(args) => list(args).await,
SessionCommands::Create(args) => create(args).await,
SessionCommands::Get(args) => get(args).await,
SessionCommands::Delete(args) => delete(args).await,
SessionCommands::Send(args) => send(args).await,
SessionCommands::Chat(args) => chat(args).await,
}
}
async fn list(args: ListArgs) -> anyhow::Result<()> {
println!("\n 💬 Sessions for '{}':\n", args.agent.bold());
let client = agentoven_core::AgentOvenClient::from_env()?;
match client.list_sessions(&args.agent).await {
Ok(sessions) => {
if sessions.is_empty() {
println!(" (no sessions — use `agentoven session create`)");
} else {
println!(
" {:<38} {:<12} {:<20}",
"SESSION ID".bold(),
"MESSAGES".bold(),
"LAST ACTIVITY".bold()
);
println!(" {}", "─".repeat(72).dimmed());
for s in &sessions {
let id = s["id"].as_str().unwrap_or("-");
let msgs = s["message_count"]
.as_u64()
.or_else(|| s["messages"].as_array().map(|a| a.len() as u64))
.unwrap_or(0);
let last = s["updated_at"].as_str().unwrap_or("-");
let last_short = if last.len() > 16 { &last[..16] } else { last };
println!(" {:<38} {:<12} {}", id, msgs, last_short);
}
println!("\n {} {} session(s)", "→".dimmed(), sessions.len());
}
}
Err(e) => {
println!(
" {} Failed: {}",
"⚠".yellow().bold(),
e.to_string().dimmed()
);
}
}
Ok(())
}
async fn create(args: CreateArgs) -> anyhow::Result<()> {
println!("\n 💬 Creating session for '{}'...\n", args.agent.bold());
let client = agentoven_core::AgentOvenClient::from_env()?;
match client.create_session(&args.agent).await {
Ok(session) => {
let id = session["id"].as_str().unwrap_or("?");
println!(" {} Session created: {}", "✓".green().bold(), id.bold());
println!("\n {} Start chatting:", "→".dimmed());
println!(" agentoven session chat {} {}", args.agent, id);
}
Err(e) => {
println!(" {} Failed: {}", "✗".red().bold(), e.to_string().dimmed());
}
}
Ok(())
}
async fn get(args: GetArgs) -> anyhow::Result<()> {
println!("\n 💬 Session: {}\n", args.session_id.bold());
let client = agentoven_core::AgentOvenClient::from_env()?;
match client.get_session(&args.agent, &args.session_id).await {
Ok(s) => {
println!(" {:<16} {}", "Agent:".bold(), args.agent);
println!(
" {:<16} {}",
"Session:".bold(),
s["id"].as_str().unwrap_or("-")
);
println!(
" {:<16} {}",
"Created:".bold(),
s["created_at"].as_str().unwrap_or("-")
);
println!(
" {:<16} {}",
"Updated:".bold(),
s["updated_at"].as_str().unwrap_or("-")
);
if let Some(messages) = s["messages"].as_array() {
println!("\n {} ({} messages):", "Messages".bold(), messages.len());
println!(" {}", "─".repeat(60).dimmed());
for msg in messages {
let role = msg["role"].as_str().unwrap_or("?");
let text = msg["content"]
.as_str()
.or_else(|| msg["text"].as_str())
.unwrap_or("");
let icon = match role {
"user" => "👤",
"assistant" => "🤖",
"system" => "⚙️ ",
_ => "·",
};
let label = match role {
"user" => "You".cyan().bold().to_string(),
"assistant" => "Agent".green().bold().to_string(),
"system" => "System".yellow().bold().to_string(),
_ => role.to_string(),
};
println!("\n {} {}:", icon, label);
for line in text.lines() {
println!(" {}", line);
}
}
}
}
Err(e) => {
println!(
" {} Not found: {}",
"⚠".yellow().bold(),
e.to_string().dimmed()
);
}
}
Ok(())
}
async fn delete(args: DeleteArgs) -> anyhow::Result<()> {
if !args.force {
let confirm = dialoguer::Confirm::new()
.with_prompt(format!(" Delete session '{}'?", args.session_id))
.default(false)
.interact()?;
if !confirm {
println!(" {} Cancelled.", "→".dimmed());
return Ok(());
}
}
let client = agentoven_core::AgentOvenClient::from_env()?;
match client.delete_session(&args.agent, &args.session_id).await {
Ok(()) => println!(" {} Session deleted.", "✓".green().bold()),
Err(e) => println!(" {} Failed: {}", "✗".red().bold(), e.to_string().dimmed()),
}
Ok(())
}
async fn send(args: SendArgs) -> anyhow::Result<()> {
let client = agentoven_core::AgentOvenClient::from_env()?;
match client
.send_session_message(&args.agent, &args.session_id, &args.message, args.thinking)
.await
{
Ok(result) => {
if let Some(reply) = result["reply"]
.as_str()
.or_else(|| result["content"].as_str())
.or_else(|| result["message"].as_str())
{
println!("\n 🤖 {}:\n", "Agent".green().bold());
for line in reply.lines() {
println!(" {}", line);
}
println!();
} else {
let pretty = serde_json::to_string_pretty(&result).unwrap_or_default();
println!("{}", pretty);
}
if args.thinking {
if let Some(thinking) = result.get("thinking") {
if let Some(t) = thinking.as_str() {
println!(" 💭 {}:", "Thinking".dimmed());
for line in t.lines() {
println!(" {}", line.dimmed());
}
println!();
}
}
}
}
Err(e) => {
println!(" {} Failed: {}", "✗".red().bold(), e.to_string().dimmed());
}
}
Ok(())
}
async fn chat(args: ChatArgs) -> anyhow::Result<()> {
let client = agentoven_core::AgentOvenClient::from_env()?;
let session_id = if let Some(id) = args.session_id {
id
} else {
match client.create_session(&args.agent).await {
Ok(s) => s["id"].as_str().unwrap_or("unknown").to_string(),
Err(e) => {
println!(" {} Failed to create session: {}", "✗".red().bold(), e);
return Ok(());
}
}
};
println!(
"\n 💬 Chat session: {} → {}",
args.agent.bold(),
session_id.dimmed()
);
println!(
" {} Type your message (Ctrl+D or 'quit' to exit)\n",
"→".dimmed()
);
while let Ok(input) = dialoguer::Input::<String>::new()
.with_prompt(format!(" {}", "You".cyan().bold()))
.allow_empty(false)
.interact_text()
{
if input.trim().eq_ignore_ascii_case("quit") || input.trim().eq_ignore_ascii_case("exit") {
break;
}
match client
.send_session_message(&args.agent, &session_id, &input, args.thinking)
.await
{
Ok(result) => {
let reply = result["reply"]
.as_str()
.or_else(|| result["content"].as_str())
.or_else(|| result["message"].as_str())
.unwrap_or("(no response)");
println!("\n 🤖 {}:\n", "Agent".green().bold());
for line in reply.lines() {
println!(" {line}");
}
println!();
}
Err(e) => {
println!(" {} Error: {}\n", "✗".red().bold(), e.to_string().dimmed());
}
}
}
println!("\n {} Session ended.", "→".dimmed());
Ok(())
}