Add excludeTurns parameter to thread/resume and thread/fork (#19014)

For callers who expect to be paginating the results for the UI, they can
now call thread/resume or thread/fork with excludeturns:true so it will
not fetch any pages of turns, and instead only set up the subscription.
That call can be immediately followed by pagination requests to
thread/turns/list to fetch pages of turns according to the UI's current
interactions.
This commit is contained in:
David de Regt
2026-04-23 10:07:59 -07:00
committed by GitHub
parent 0b4f694347
commit 3d3028a5a9
14 changed files with 420 additions and 100 deletions

View File

@@ -17,6 +17,7 @@ use codex_app_server_protocol::Thread;
use codex_app_server_protocol::ThreadHistoryBuilder;
use codex_app_server_protocol::ThreadTokenUsage;
use codex_app_server_protocol::ThreadTokenUsageUpdatedNotification;
use codex_app_server_protocol::Turn;
use codex_app_server_protocol::TurnStatus;
use codex_core::CodexThread;
use codex_protocol::ThreadId;
@@ -60,15 +61,15 @@ pub(super) async fn send_thread_token_usage_update_to_connection(
pub(super) async fn latest_token_usage_turn_id_for_thread_path(thread: &Thread) -> Option<String> {
let rollout_path = thread.path.as_deref()?;
latest_token_usage_turn_id_from_rollout_path(rollout_path, thread).await
latest_token_usage_turn_id_from_rollout_path(rollout_path, thread.turns.as_slice()).await
}
pub(super) async fn latest_token_usage_turn_id_from_rollout_path(
rollout_path: &Path,
thread: &Thread,
turns: &[Turn],
) -> Option<String> {
let rollout_items = read_rollout_items_from_rollout(rollout_path).await.ok()?;
latest_token_usage_turn_id_from_rollout_items(&rollout_items, thread)
latest_token_usage_turn_id_from_rollout_items(&rollout_items, turns)
}
/// Identifies the turn that was active when a `TokenCount` record appeared.
@@ -82,21 +83,8 @@ struct TokenUsageTurnOwner {
pub(super) fn latest_token_usage_turn_id_from_rollout_items(
rollout_items: &[RolloutItem],
thread: &Thread,
turns: &[Turn],
) -> Option<String> {
let owner = latest_token_usage_turn_owner_from_rollout_items(rollout_items)?;
if thread.turns.iter().any(|turn| turn.id == owner.id) {
return Some(owner.id);
}
owner
.position
.and_then(|position| thread.turns.get(position))
.map(|turn| turn.id.clone())
}
fn latest_token_usage_turn_owner_from_rollout_items(
rollout_items: &[RolloutItem],
) -> Option<TokenUsageTurnOwner> {
let mut builder = ThreadHistoryBuilder::new();
let mut token_usage_turn_owner = None;
@@ -113,7 +101,15 @@ fn latest_token_usage_turn_owner_from_rollout_items(
builder.handle_rollout_item(item);
}
token_usage_turn_owner
let owner = token_usage_turn_owner?;
if turns.iter().any(|turn| turn.id == owner.id) {
Some(owner.id)
} else {
owner
.position
.and_then(|position| turns.get(position))
.map(|turn| turn.id.clone())
}
}
/// Chooses a fallback turn id that should own a replayed token usage update.