From 33c1aba86e014dcde5eb5239c9d7137c93d31115 Mon Sep 17 00:00:00 2001 From: "Dhanji R. Prasanna" Date: Sun, 11 Jan 2026 06:22:20 +0800 Subject: [PATCH] Show human-readable descriptions in /resume session list - Add description field to SessionContinuation struct - Extract first user message (truncated to ~60 chars at word boundary) - Display as quoted text instead of session ID hash - Fall back to session ID if no description available Example: [2 hours ago] 'when I call /resume it only shows me 2 sessions...' --- crates/g3-cli/src/lib.rs | 16 +++++++------ crates/g3-core/src/lib.rs | 28 ++++++++++++++++++++++ crates/g3-core/src/session_continuation.rs | 5 ++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/crates/g3-cli/src/lib.rs b/crates/g3-cli/src/lib.rs index 418063e..96d81df 100644 --- a/crates/g3-cli/src/lib.rs +++ b/crates/g3-cli/src/lib.rs @@ -1852,16 +1852,18 @@ async fn run_interactive( }; let todo_marker = if session.has_incomplete_todos() { " 📝" } else { "" }; - // Truncate session ID for display - let display_id = if session.session_id.len() > 40 { - format!("{}...", &session.session_id[..40]) - } else { - session.session_id.clone() + // Use description if available, otherwise fall back to session ID + let display_name = match &session.description { + Some(desc) => format!("'{}'", desc), + None => if session.session_id.len() > 40 { + format!("{}...", &session.session_id[..40]) + } else { + session.session_id.clone() + } }; - output.print(&format!( " {}. [{}] {} ({}){}{}", - i + 1, time_str, display_id, context_str, todo_marker, current_marker + i + 1, time_str, display_name, context_str, todo_marker, current_marker )); } output.print(""); diff --git a/crates/g3-core/src/lib.rs b/crates/g3-core/src/lib.rs index ddd61cd..d3591ba 100644 --- a/crates/g3-core/src/lib.rs +++ b/crates/g3-core/src/lib.rs @@ -1405,10 +1405,20 @@ impl Agent { .map(|p| p.to_string_lossy().to_string()) .unwrap_or_else(|_| ".".to_string()); + // Get description from first user message (strip "Task: " prefix if present) + let description = self.context_window.conversation_history.iter() + .find(|m| matches!(m.role, g3_providers::MessageRole::User)) + .map(|m| { + let content = m.content.strip_prefix("Task: ").unwrap_or(&m.content); + // Truncate to ~60 chars for display, ending at word boundary + truncate_to_word_boundary(content, 60) + }); + let continuation = SessionContinuation::new( self.is_agent_mode, self.agent_name.clone(), session_id, + description, summary, session_log_path.to_string_lossy().to_string(), self.context_window.percentage_used(), @@ -2831,6 +2841,24 @@ impl Agent { // Re-export utility functions pub use utils::apply_unified_diff_to_string; +/// Truncate a string to approximately max_len characters, ending at a word boundary +fn truncate_to_word_boundary(s: &str, max_len: usize) -> String { + if s.len() <= max_len { + return s.to_string(); + } + + // Find the last space before max_len + let truncated = &s[..max_len]; + if let Some(last_space) = truncated.rfind(' ') { + if last_space > max_len / 2 { + // Only use word boundary if it's not too short + return format!("{}...", &s[..last_space]); + } + } + // Fall back to character truncation + format!("{}...", truncated) +} + // Implement Drop to clean up safaridriver process impl Drop for Agent { fn drop(&mut self) { diff --git a/crates/g3-core/src/session_continuation.rs b/crates/g3-core/src/session_continuation.rs index f293ab0..edce8aa 100644 --- a/crates/g3-core/src/session_continuation.rs +++ b/crates/g3-core/src/session_continuation.rs @@ -32,6 +32,9 @@ pub struct SessionContinuation { pub created_at: String, /// Original session ID pub session_id: String, + /// Human-readable description (first user message, truncated) + #[serde(default)] + pub description: Option, /// Session summary (last assistant response) pub summary: Option, /// Path to the full session log (g3_session_*.json) @@ -50,6 +53,7 @@ impl SessionContinuation { is_agent_mode: bool, agent_name: Option, session_id: String, + description: Option, summary: Option, session_log_path: String, context_percentage: f32, @@ -62,6 +66,7 @@ impl SessionContinuation { agent_name, created_at: chrono::Utc::now().to_rfc3339(), session_id, + description, summary, session_log_path, context_percentage,