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...'
This commit is contained in:
Dhanji R. Prasanna
2026-01-11 06:22:20 +08:00
parent 3fcef587e8
commit 33c1aba86e
3 changed files with 42 additions and 7 deletions

View File

@@ -1852,16 +1852,18 @@ async fn run_interactive<W: UiWriter>(
};
let todo_marker = if session.has_incomplete_todos() { " 📝" } else { "" };
// Truncate session ID for display
let display_id = if session.session_id.len() > 40 {
// 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("");

View File

@@ -1405,10 +1405,20 @@ impl<W: UiWriter> Agent<W> {
.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<W: UiWriter> Agent<W> {
// 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<W: UiWriter> Drop for Agent<W> {
fn drop(&mut self) {

View File

@@ -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<String>,
/// Session summary (last assistant response)
pub summary: Option<String>,
/// Path to the full session log (g3_session_*.json)
@@ -50,6 +53,7 @@ impl SessionContinuation {
is_agent_mode: bool,
agent_name: Option<String>,
session_id: String,
description: Option<String>,
summary: Option<String>,
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,