Show Codex background task counts

This commit is contained in:
iris-ai committed 2026-09-15 23:26:37 -04:00
1 parent 947ea8ecf2
commit a9cfea89e5
5 files changed
+155 -52

No files matched your search

+81 -18
View File
@@ -64,11 +64,19 @@ impl Translator {
/// Translates one multiplexed app-server record. `prefix` contains image
/// events extracted by the driver and must precede the item's ToolEnd in
/// whichever transcript owns the record.
pub(super) fn translate_with_prefix(
&mut self,
line: &Value,
mut prefix: Vec<Event>,
) -> Vec<Event> {
pub(super) fn translate_with_prefix(&mut self, line: &Value, prefix: Vec<Event>) -> Vec<Event> {
let before = self.background_task_count();
let mut events = self.translate_inner(line, prefix);
let after = self.background_task_count();
if after != before
&& let Some(count) = after
{
events.push(Event::BackgroundTasks { count });
}
events
}
fn translate_inner(&mut self, line: &Value, mut prefix: Vec<Event>) -> Vec<Event> {
let method = line.get("method").and_then(Value::as_str);
let body = method.and_then(|_| line.get("params")).unwrap_or(line);
let kind = method.or_else(|| line.get("type").and_then(Value::as_str));
@@ -109,6 +117,12 @@ impl Translator {
prefix
}
fn background_task_count(&self) -> Option<usize> {
self.subagents
.as_ref()
.map(|subagents| subagents.open_count())
}
fn translate_line(&mut self, kind: Option<&str>, body: &Value, line: &Value) -> Vec<Event> {
match kind {
Some("thread.started") => {
@@ -1222,10 +1236,13 @@ mod tests {
translator.translate(&line(
r#"{"method":"item/completed","params":{"threadId":"parent-thread","turnId":"turn-1","item":{"id":"spawn-1","type":"subAgentActivity","kind":"started","agentThreadId":"child-thread","agentPath":"/root/history_boundaries"}}}"#
)),
vec![Event::ToolEnd {
id: "spawn-1".to_string(),
output: String::new()
}]
vec![
Event::ToolEnd {
id: "spawn-1".to_string(),
output: String::new()
},
Event::BackgroundTasks { count: 1 }
]
);
let rows = subagents.list(true);
assert_eq!(rows.len(), 1);
@@ -1265,9 +1282,12 @@ mod tests {
translator.translate(&line(
r#"{"method":"item/completed","params":{"threadId":"parent-thread","turnId":"turn-1","item":{"id":"subagent-completed-1","type":"subAgentActivity","kind":"completed","agentThreadId":"child-thread","agentPath":"/root/history_boundaries"}}}"#
)),
vec![Event::Status {
state: SessionStatus::Idle
}]
vec![
Event::Status {
state: SessionStatus::Idle
},
Event::BackgroundTasks { count: 0 }
]
);
let child = subagents.get("child-thread").expect("child");
@@ -1289,6 +1309,50 @@ mod tests {
);
}
#[test]
fn codex_reports_each_change_to_its_live_background_count() {
let dir = tempfile::tempdir().expect("tempdir");
let subagents = Arc::new(Subagents::new(dir.path().to_path_buf()));
let mut translator = Translator::new(
Arc::clone(&subagents),
Some("parent-thread".to_string()),
false,
);
for (call, child, count) in [("spawn-a", "child-a", 1), ("spawn-b", "child-b", 2)] {
let events = translator.translate(&json!({
"method": "item/completed",
"params": {
"threadId": "parent-thread",
"item": {
"id": call,
"type": "subAgentActivity",
"kind": "started",
"agentThreadId": child,
"agentPath": format!("/root/{child}")
}
}
}));
assert_eq!(events.last(), Some(&Event::BackgroundTasks { count }));
}
for (child, count) in [("child-a", 1), ("child-b", 0)] {
let events = translator.translate(&json!({
"method": "item/completed",
"params": {
"threadId": "parent-thread",
"item": {
"id": format!("completed-{child}"),
"type": "subAgentActivity",
"kind": "completed",
"agentThreadId": child,
"agentPath": format!("/root/{child}")
}
}
}));
assert_eq!(events.last(), Some(&Event::BackgroundTasks { count }));
}
}
#[test]
fn codex_collaboration_coordination_has_clean_parent_tool_cards() {
let mut translator = Translator::default();
@@ -1430,12 +1494,11 @@ mod tests {
true,
);
assert!(
translator
.translate(&line(
r#"{"method":"item/completed","params":{"threadId":"parent-thread","turnId":"turn-1","item":{"id":"subagent-completed-1","type":"subAgentActivity","kind":"completed","agentThreadId":"child-thread","agentPath":"/root/child"}}}"#
))
.is_empty()
assert_eq!(
translator.translate(&line(
r#"{"method":"item/completed","params":{"threadId":"parent-thread","turnId":"turn-1","item":{"id":"subagent-completed-1","type":"subAgentActivity","kind":"completed","agentThreadId":"child-thread","agentPath":"/root/child"}}}"#
)),
vec![Event::BackgroundTasks { count: 0 }]
);
assert_eq!(subagents.list(true)[0].status, SessionStatus::Exited);
}