Update header from Working once batched commands are done (#2249)

Update commands from Working to Complete or Failed after they're done

before:
<img width="725" height="332" alt="image"
src="https://github.com/user-attachments/assets/fb93d21f-5c4a-42bc-a154-14f4fe99d5f9"
/>

after:
<img width="464" height="65" alt="image"
src="https://github.com/user-attachments/assets/15ec7c3b-355f-473e-9a8e-eab359ec5f0d"
/>
This commit is contained in:
easong-openai
2025-08-13 11:10:48 -07:00
committed by GitHub
parent 0159bc7bdb
commit cb312dfdb4
3 changed files with 129 additions and 7 deletions

View File

@@ -76,6 +76,7 @@ pub(crate) struct ChatWidget<'a> {
// Track the most recently active stream kind in the current turn
last_stream_kind: Option<StreamKind>,
running_commands: HashMap<String, RunningCommand>,
pending_exec_completions: Vec<(Vec<String>, Vec<ParsedCommand>, CommandOutput)>,
task_complete_pending: bool,
// Queue of interruptive UI events deferred during an active write cycle
interrupts: InterruptManager,
@@ -112,6 +113,10 @@ impl ChatWidget<'_> {
fn mark_needs_redraw(&mut self) {
self.needs_redraw = true;
}
fn flush_answer_stream_with_separator(&mut self) {
let sink = AppEventHistorySink(self.app_event_tx.clone());
let _ = self.stream.finalize(StreamKind::Answer, true, &sink);
}
// --- Small event handlers ---
fn on_session_configured(&mut self, event: codex_core::protocol::SessionConfiguredEvent) {
self.bottom_pane
@@ -215,6 +220,7 @@ impl ChatWidget<'_> {
}
fn on_exec_command_begin(&mut self, ev: ExecCommandBeginEvent) {
self.flush_answer_stream_with_separator();
let ev2 = ev.clone();
self.defer_or_handle(|q| q.push_exec_begin(ev), |s| s.handle_exec_begin_now(ev2));
}
@@ -344,12 +350,11 @@ impl ChatWidget<'_> {
pub(crate) fn handle_exec_end_now(&mut self, ev: ExecCommandEndEvent) {
let running = self.running_commands.remove(&ev.call_id);
self.active_exec_cell = None;
let (command, parsed) = match running {
Some(rc) => (rc.command, rc.parsed_cmd),
None => (vec![ev.call_id.clone()], Vec::new()),
};
self.add_to_history(HistoryCell::new_completed_exec_command(
self.pending_exec_completions.push((
command,
parsed,
CommandOutput {
@@ -358,6 +363,16 @@ impl ChatWidget<'_> {
stderr: ev.stderr.clone(),
},
));
if self.running_commands.is_empty() {
self.active_exec_cell = None;
let pending = std::mem::take(&mut self.pending_exec_completions);
for (command, parsed, output) in pending {
self.add_to_history(HistoryCell::new_completed_exec_command(
command, parsed, output,
));
}
}
}
pub(crate) fn handle_patch_apply_end_now(
@@ -372,6 +387,7 @@ impl ChatWidget<'_> {
}
pub(crate) fn handle_exec_approval_now(&mut self, id: String, ev: ExecApprovalRequestEvent) {
self.flush_answer_stream_with_separator();
// Log a background summary immediately so the history is chronological.
let cmdline = strip_bash_lc_and_escape(&ev.command);
let text = format!(
@@ -398,6 +414,7 @@ impl ChatWidget<'_> {
id: String,
ev: ApplyPatchApprovalRequestEvent,
) {
self.flush_answer_stream_with_separator();
self.add_to_history(HistoryCell::new_patch_event(
PatchEventType::ApprovalRequest,
ev.changes.clone(),
@@ -423,16 +440,29 @@ impl ChatWidget<'_> {
parsed_cmd: ev.parsed_cmd.clone(),
},
);
self.active_exec_cell = Some(HistoryCell::new_active_exec_command(
ev.command,
ev.parsed_cmd,
));
// Accumulate parsed commands into a single active Exec cell so they stack
match self.active_exec_cell.as_mut() {
Some(HistoryCell::Exec(exec)) => {
exec.parsed.extend(ev.parsed_cmd);
}
_ => {
self.active_exec_cell = Some(HistoryCell::new_active_exec_command(
ev.command,
ev.parsed_cmd,
));
}
}
// Request a redraw so the working header and command list are visible immediately.
self.mark_needs_redraw();
}
pub(crate) fn handle_mcp_begin_now(&mut self, ev: McpToolCallBeginEvent) {
self.flush_answer_stream_with_separator();
self.add_to_history(HistoryCell::new_active_mcp_tool_call(ev.invocation));
}
pub(crate) fn handle_mcp_end_now(&mut self, ev: McpToolCallEndEvent) {
self.flush_answer_stream_with_separator();
self.add_to_history(HistoryCell::new_completed_mcp_tool_call(
80,
ev.invocation,
@@ -494,6 +524,7 @@ impl ChatWidget<'_> {
stream: StreamController::new(config),
last_stream_kind: None,
running_commands: HashMap::new(),
pending_exec_completions: Vec::new(),
task_complete_pending: false,
interrupts: InterruptManager::new(),
needs_redraw: false,