Limit the agent command center to 10 recent sessions on startup (#46579)

## What changed

Reduce the initial recent-session seed from 20 to 10, alongside loaded sessions. Use a shared `RECENT_SESSION_LIMIT` for pagination, collection, and final truncation.

## Testing

Update the overview test for the 10-session limit and add a snapshot of the recent-session list after restart.

GitOrigin-RevId: f315f4848e8d2091eb229cfdc3c02932aaf7ba8c
This commit is contained in:
Eric Traut
2026-09-19 02:08:25 +00:00
committed by copyberry
parent 29a57861e3
commit 6b78e825ae
3 changed files with 50 additions and 13 deletions

View File

@@ -430,7 +430,7 @@ async fn shared_overview_seeds_once_and_retains_locally_resumed_history() -> Res
let mut app = make_test_app().await;
trust_fixture_folders(&mut app);
let mut ids = Vec::new();
for day in 1..=22 {
for day in 1..=12 {
let source = match day {
3 => codex_protocol::protocol::SessionSource::Custom("atlas".to_string()),
4 => codex_protocol::protocol::SessionSource::Custom("chatgpt".to_string()),
@@ -457,13 +457,13 @@ async fn shared_overview_seeds_once_and_retains_locally_resumed_history() -> Res
}
let message_path = app_test_support::rollout_path(
&app.config.codex_home,
"2025-01-21T12-00-00",
&ids[20].to_string(),
"2025-01-11T12-00-00",
&ids[10].to_string(),
);
let mut history = std::fs::read_to_string(&message_path)?;
history.push_str(
&serde_json::json!({
"timestamp": "2025-01-21T12:00:01Z",
"timestamp": "2025-01-11T12:00:01Z",
"type": "event_msg",
"payload": { "type": "agent_message", "message": "Found the regression in the parser." }
})
@@ -473,7 +473,7 @@ async fn shared_overview_seeds_once_and_retains_locally_resumed_history() -> Res
std::fs::write(message_path, history)?;
let config = app.config.clone();
let mut app_server = Box::pin(crate::start_embedded_app_server_for_picker(&config)).await?;
for thread_id in [ids[0], ids[21]] {
for thread_id in [ids[0], ids[11]] {
app_server
.resume_thread(
&app.local_settings,
@@ -486,8 +486,8 @@ async fn shared_overview_seeds_once_and_retains_locally_resumed_history() -> Res
// A newer rollout missing from the index must not trigger a startup filesystem scan.
app_test_support::create_fake_rollout_with_source(
&app.config.codex_home,
"2025-01-23T12-00-00",
"2025-01-23T12:00:00Z",
"2025-01-13T12-00-00",
"2025-01-13T12:00:00Z",
"Unindexed task",
Some(&app.config.model_provider_id),
/*git_info*/ None,
@@ -511,9 +511,9 @@ async fn shared_overview_seeds_once_and_retains_locally_resumed_history() -> Res
assert_eq!(retained, expected);
assert_eq!(
app.agents_overview.last_messages,
HashMap::from([(ids[20], "Found the regression in the parser.".to_string())])
HashMap::from([(ids[10], "Found the regression in the parser.".to_string())])
);
let thread = app.agents_overview.threads[&ids[20]].as_ref().unwrap();
let thread = app.agents_overview.threads[&ids[10]].as_ref().unwrap();
assert_eq!(thread.status, ThreadStatus::NotLoaded);
let created = app_server.start_thread(&config).await?.session.thread_id;
@@ -596,6 +596,12 @@ async fn shared_overview_seeds_once_and_retains_locally_resumed_history() -> Res
finish_overview_refresh(&mut restarted, &app_server, &mut event_rx).await;
let retained: HashSet<_> = restarted.agents_overview.threads.keys().copied().collect();
assert_eq!(retained, recent_ids);
restarted.open_agents_overview(&app_server);
insta::assert_snapshot!(
"agents_overview_recent_sessions",
render_bottom_popup(&restarted.chat_widget, /*width*/ 80)
.replace(&test_path_display("/"), "/")
);
app_server.shutdown().await?;
Ok(())
}

View File

@@ -34,6 +34,9 @@ use codex_protocol::protocol::SubAgentSource;
use std::collections::HashMap;
use uuid::Uuid;
// Seed the command center with this many recent sessions, in addition to loaded sessions.
const RECENT_SESSION_LIMIT: usize = 10;
impl App {
pub(super) fn track_agents_overview_notification(&mut self, notification: &ServerNotification) {
let ServerNotificationThreadTarget::Thread(thread_id) =
@@ -226,14 +229,14 @@ impl App {
let mut recent = Vec::new();
let mut cursor = None;
let mut sort_key = ThreadSortKey::RecencyAt;
while recent.len() < 20 {
while recent.len() < RECENT_SESSION_LIMIT {
let page = match request_handle
.request_typed::<ThreadListResponse>(ClientRequest::ThreadList {
request_id: RequestId::String(Uuid::new_v4().to_string()),
params: ThreadListParams {
originators: None,
cursor,
limit: Some(20),
limit: Some(RECENT_SESSION_LIMIT as u32),
sort_key: Some(sort_key),
sort_direction: None,
model_providers: Some(Vec::new()),
@@ -276,7 +279,7 @@ impl App {
)
)
})
.take(20 - recent.len()),
.take(RECENT_SESSION_LIMIT - recent.len()),
);
cursor = page.next_cursor;
if cursor.is_none() {
@@ -301,7 +304,7 @@ impl App {
.cmp(&left.recency_at.unwrap_or(left.updated_at))
.then_with(|| right.id.cmp(&left.id))
});
recent.truncate(20);
recent.truncate(RECENT_SESSION_LIMIT);
Ok::<_, TypedRequestError>(recent)
};
let (loaded, recent) = tokio::join!(loaded, recent);

View File

@@ -0,0 +1,28 @@
---
source: tui/src/app/agents_overview_tests.rs
expression: "render_bottom_popup(&restarted.chat_widget,\n80).replace(&test_path_display(\"/\"), \"/\")"
---
Agent command center
0 need input 0 working 0 ready
────────────────────────────────────────────────────────────────────────────
/ 10
✓ Task 12 Finished
✓ Task 11 Finished
✓ Task 10 Finished
✓ Task 9 Finished
✓ Task 8 Finished
✓ Task 7 Finished
✓ Task 6 Finished
✓ Task 5 Finished
✓ Task 4 Finished
✓ Task 3 Finished
↑↓ navigate o resume enter open n new w new worktree f search
g group: project r rename x stop h hide a archive del delete ctrl+c quit