Draw a background task as what it ran, and go there on a tap
A card in the session's panel said "background command" under every description -- and for Codex, which names a terminal by a process id and gives no description at all, that phrase was the whole of every card. Both halves of the answer are in the transcript rather than in what the provider says: a driver now reports which tool call its task belongs to (Claude's `task_started` carries the `tool_use_id`, Codex's terminal list the `itemId`), and `LiveSession::background_tasks` resolves those ids against the transcript into a sequence number and, where the provider said nothing, the command the call was made with. So the card draws the command, and the kind shrinks to a mark beside it whose name is what a screen reader is given. Tapping one goes to that call in the transcript, opened, which is where a backgrounded command's output already lands -- rather than drawing a second copy of it beside the panel. The journey is the one a reopened session already makes to put a reader back where they stopped, now one function (`travelTo`). It has to release the held backlog first: events arriving while the reader is away from the newest end are held rather than applied, so a task started since they scrolled back was in no row at all and the tap looked like it had done nothing. Verified against the sandbox on the emulator: the panel draws `sleep 120 && echo done` for an echo session's `/background`, and tapping it lands on that Bash card with its output showing.
This commit is contained in:
1 parent
3b309766d7
commit
cedb18e8c1
18 files changed
+635
-151
No files matched your search
@@ -5,7 +5,7 @@
|
||||
//! ignore the rest; an added Codex item must not make a live session go deaf.
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
|
||||
use serde_json::{Value, json};
|
||||
|
||||
@@ -18,7 +18,7 @@ pub(super) struct Translator {
|
||||
completed: bool,
|
||||
limited: bool,
|
||||
subagents: Option<Arc<Subagents>>,
|
||||
background_processes: Option<Arc<Mutex<HashSet<String>>>>,
|
||||
background_processes: Option<super::BackgroundProcesses>,
|
||||
children: HashMap<String, Translator>,
|
||||
prompts: HashMap<String, String>,
|
||||
async_messages: HashSet<String>,
|
||||
@@ -28,7 +28,7 @@ pub(super) struct Translator {
|
||||
impl Translator {
|
||||
pub(super) fn new(
|
||||
subagents: Arc<Subagents>,
|
||||
background_processes: Arc<Mutex<HashSet<String>>>,
|
||||
background_processes: super::BackgroundProcesses,
|
||||
thread_id: Option<String>,
|
||||
in_turn: bool,
|
||||
) -> Self {
|
||||
@@ -912,6 +912,9 @@ fn find_reset(value: &Value) -> Option<f64> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn line(text: &str) -> Value {
|
||||
@@ -1231,7 +1234,7 @@ mod tests {
|
||||
fn codex_subagents_get_their_own_transcripts_and_hold_the_parent_waiting() {
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let subagents = Arc::new(Subagents::new(dir.path().to_path_buf()));
|
||||
let background_processes = Arc::new(Mutex::new(HashSet::new()));
|
||||
let background_processes = Arc::new(Mutex::new(BTreeMap::new()));
|
||||
let mut translator = Translator::new(
|
||||
Arc::clone(&subagents),
|
||||
Arc::clone(&background_processes),
|
||||
@@ -1330,7 +1333,7 @@ mod tests {
|
||||
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 background_processes = Arc::new(Mutex::new(HashSet::new()));
|
||||
let background_processes = Arc::new(Mutex::new(BTreeMap::new()));
|
||||
let mut translator = Translator::new(
|
||||
Arc::clone(&subagents),
|
||||
Arc::clone(&background_processes),
|
||||
@@ -1357,7 +1360,7 @@ mod tests {
|
||||
background_processes
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert("command-a".to_string());
|
||||
.insert("command-a".to_string(), None);
|
||||
for (child, count) in [("child-a", 2), ("child-b", 1)] {
|
||||
let events = translator.translate(&json!({
|
||||
"method": "item/completed",
|
||||
@@ -1521,7 +1524,7 @@ mod tests {
|
||||
subagents.start("child-thread", "child", Some("work"));
|
||||
let mut translator = Translator::new(
|
||||
Arc::clone(&subagents),
|
||||
Arc::new(Mutex::new(HashSet::new())),
|
||||
Arc::new(Mutex::new(BTreeMap::new())),
|
||||
Some("parent-thread".to_string()),
|
||||
true,
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user