feat(sessions): add Sub-agents count column to sessions list

Call discover_agents_for_session for each session and show the real
count in a new Sub-agents column. JSON and XML output updated to include
the subagents field.

Closes claudbg-xpzp

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
Elijah Voigt 2 months ago
parent 4fd09045d0
commit 68a795bacd

@ -1,11 +1,11 @@
--- ---
# claudbg-xpzp # claudbg-xpzp
title: '`sessions list` should show sub-agent run count per session' title: '`sessions list` should show sub-agent run count per session'
status: todo status: completed
type: bug type: bug
priority: normal priority: normal
created_at: 2026-03-30T04:40:53Z created_at: 2026-03-30T04:40:53Z
updated_at: 2026-03-30T04:43:26Z updated_at: 2026-03-30T05:15:27Z
parent: claudbg-tci9 parent: claudbg-tci9
blocked_by: blocked_by:
- claudbg-33n0 - claudbg-33n0
@ -40,3 +40,7 @@ The existing `discover_agents_for_session(session_file)` function currently look
- `src/commands/sessions.rs``list()` function - `src/commands/sessions.rs``list()` function
- `src/parser/discovery.rs``discover_agents_for_session` - `src/parser/discovery.rs``discover_agents_for_session`
## Summary of Changes
In sessions.rs list(): built a session_id->file_path map from discovered sessions, then for each DB row called discover_agents_for_session to get the real count. Added 'Sub-agents' column to table headers and row data. Updated JSON and XML output to include the subagents field.

@ -161,6 +161,12 @@ pub async fn list(opts: &crate::cli::GlobalOpts) -> Result<()> {
crate::db::sync::ensure_synced(&db, session_ref).await?; crate::db::sync::ensure_synced(&db, session_ref).await?;
} }
// Build a map from session_id -> file_path for agent discovery.
let session_file_map: std::collections::HashMap<String, std::path::PathBuf> = sessions
.into_iter()
.map(|sr| (sr.session_id, sr.file_path))
.collect();
// Query DB for display. // Query DB for display.
let conn = db let conn = db
.connect() .connect()
@ -206,18 +212,31 @@ pub async fn list(opts: &crate::cli::GlobalOpts) -> Result<()> {
project_path project_path
}; };
// Count sub-agents for this session.
let agent_count = if let Some(file_path) = session_file_map.get(&session_id) {
crate::parser::discovery::discover_agents_for_session(file_path)
.unwrap_or_default()
.len()
} else {
0
};
rows.push(vec![ rows.push(vec![
display_id, display_id,
last_msg_at, last_msg_at,
display_path, display_path,
model, model,
message_count.to_string(), message_count.to_string(),
agent_count.to_string(),
]); ]);
} }
let output = match opts.output { let output = match opts.output {
crate::cli::OutputFormat::Table => { crate::cli::OutputFormat::Table => {
crate::output::render_table(&["ID", "Date", "Project", "Model", "Messages"], &rows)? crate::output::render_table(
&["ID", "Date", "Project", "Model", "Messages", "Sub-agents"],
&rows,
)?
} }
crate::cli::OutputFormat::Json => { crate::cli::OutputFormat::Json => {
let objects: Vec<serde_json::Value> = rows let objects: Vec<serde_json::Value> = rows
@ -229,14 +248,14 @@ pub async fn list(opts: &crate::cli::GlobalOpts) -> Result<()> {
"project": r[2], "project": r[2],
"model": r[3], "model": r[3],
"messages": r[4], "messages": r[4],
"subagents": 0, "subagents": r[5],
}) })
}) })
.collect(); .collect();
crate::output::render_json(&objects)? crate::output::render_json(&objects)?
} }
crate::cli::OutputFormat::Xml => crate::output::render_xml_rows( crate::cli::OutputFormat::Xml => crate::output::render_xml_rows(
&["session_id", "date", "project", "model", "messages"], &["session_id", "date", "project", "model", "messages", "subagents"],
&rows, &rows,
)?, )?,
}; };

Loading…
Cancel
Save