From f1a5241777f50197ef2ac77ed3dd52e27a94f575 Mon Sep 17 00:00:00 2001 From: "Dhanji R. Prasanna" Date: Fri, 30 Jan 2026 14:06:28 +1100 Subject: [PATCH] Add /research and /research latest commands Allow users to view research reports directly from the CLI: - /research - List all research tasks (unchanged) - /research - View the full report for a specific research task - /research latest - View the most recent completed research report Report display includes query, status, elapsed time, and full content. --- crates/g3-cli/src/commands.rs | 64 ++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/crates/g3-cli/src/commands.rs b/crates/g3-cli/src/commands.rs index 42077f7..e74aedb 100644 --- a/crates/g3-cli/src/commands.rs +++ b/crates/g3-cli/src/commands.rs @@ -39,6 +39,8 @@ pub async fn handle_command( output.print(" /rehydrate - Restore a dehydrated fragment by ID"); output.print(" /resume - List and switch to a previous session"); output.print(" /research - List pending/completed research tasks"); + output.print(" /research - View a specific research report"); + output.print(" /research latest - View the most recent research report"); output.print(" /project - Load a project from the given absolute path"); output.print(" /unproject - Unload the current project and reset context"); output.print(" /dump - Dump entire context window to file for debugging"); @@ -131,13 +133,19 @@ pub async fn handle_command( } Ok(true) } - "/research" => { + cmd if cmd == "/research" || cmd.starts_with("/research ") => { let manager = agent.get_pending_research_manager(); - let all_tasks = manager.list_all(); - if all_tasks.is_empty() { + // Parse argument: /research, /research latest, /research + let arg = cmd.strip_prefix("/research").unwrap_or("").trim(); + + if arg.is_empty() { + // List all research tasks + let all_tasks = manager.list_all(); + + if all_tasks.is_empty() { output.print("📋 No research tasks (pending or completed)."); - } else { + } else { output.print(&format!("📋 Research Tasks ({} total):\n", all_tasks.len())); for task in all_tasks { @@ -163,6 +171,54 @@ pub async fn handle_command( } )); output.print(""); + } + } + } else if arg == "latest" { + // Show the most recent research report + let all_tasks = manager.list_all(); + + // Find the most recent completed task (smallest elapsed time = most recent) + let latest = all_tasks.iter() + .filter(|t| t.status != g3_core::pending_research::ResearchStatus::Pending) + .min_by_key(|t| t.started_at.elapsed()); + + match latest { + Some(task) => { + output.print(&format!("📋 Research Report: `{}`\n", task.id)); + output.print(&format!("Query: {}\n", task.query)); + output.print(&format!("Status: {} | Elapsed: {}\n", task.status, task.elapsed_display())); + output.print(&"─".repeat(60)); + if let Some(ref result) = task.result { + output.print(result); + } else { + output.print("(No report content available)"); + } + } + None => { + output.print("📋 No completed research tasks yet."); + } + } + } else { + // View a specific research report by ID + let task_id = arg.to_string(); + + match manager.get(&task_id) { + Some(task) => { + output.print(&format!("📋 Research Report: `{}`\n", task.id)); + output.print(&format!("Query: {}\n", task.query)); + output.print(&format!("Status: {} | Elapsed: {}\n", task.status, task.elapsed_display())); + output.print(&"─".repeat(60)); + if let Some(ref result) = task.result { + output.print(result); + } else if task.status == g3_core::pending_research::ResearchStatus::Pending { + output.print("(Research still in progress...)"); + } else { + output.print("(No report content available)"); + } + } + None => { + output.print(&format!("❓ No research task found with id: `{}`", task_id)); + } } } Ok(true)