Render exec output deltas inline (#9194)

This commit is contained in:
Ahmed Ibrahim 2026-01-14 08:11:12 -08:00 committed by GitHub
parent 7532f34699
commit bdae0035ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 52 additions and 10 deletions

View file

@ -54,6 +54,7 @@ use codex_core::protocol::EventMsg;
use codex_core::protocol::ExecApprovalRequestEvent;
use codex_core::protocol::ExecCommandBeginEvent;
use codex_core::protocol::ExecCommandEndEvent;
use codex_core::protocol::ExecCommandOutputDeltaEvent;
use codex_core::protocol::ExecCommandSource;
use codex_core::protocol::ExitedReviewModeEvent;
use codex_core::protocol::ListCustomPromptsResponseEvent;
@ -1017,11 +1018,19 @@ impl ChatWidget {
self.defer_or_handle(|q| q.push_exec_begin(ev), |s| s.handle_exec_begin_now(ev2));
}
fn on_exec_command_output_delta(
&mut self,
_ev: codex_core::protocol::ExecCommandOutputDeltaEvent,
) {
// TODO: Handle streaming exec output if/when implemented
fn on_exec_command_output_delta(&mut self, ev: ExecCommandOutputDeltaEvent) {
let Some(cell) = self
.active_cell
.as_mut()
.and_then(|c| c.as_any_mut().downcast_mut::<ExecCell>())
else {
return;
};
if cell.append_output(&ev.call_id, std::str::from_utf8(&ev.chunk).unwrap_or("")) {
self.bump_active_cell_revision();
self.request_redraw();
}
}
fn on_terminal_interaction(&mut self, ev: TerminalInteractionEvent) {

View file

@ -125,6 +125,18 @@ impl ExecCell {
self.calls.iter()
}
pub(crate) fn append_output(&mut self, call_id: &str, chunk: &str) -> bool {
if chunk.is_empty() {
return false;
}
let Some(call) = self.calls.iter_mut().rev().find(|c| c.call_id == call_id) else {
return false;
};
let output = call.output.get_or_insert_with(CommandOutput::default);
output.aggregated_output.push_str(chunk);
true
}
pub(super) fn is_exploring_call(call: &ExecCall) -> bool {
!matches!(call.source, ExecCommandSource::UserShell)
&& !call.parsed.is_empty()

View file

@ -53,6 +53,7 @@ use codex_core::protocol::EventMsg;
use codex_core::protocol::ExecApprovalRequestEvent;
use codex_core::protocol::ExecCommandBeginEvent;
use codex_core::protocol::ExecCommandEndEvent;
use codex_core::protocol::ExecCommandOutputDeltaEvent;
use codex_core::protocol::ExecCommandSource;
use codex_core::protocol::ExitedReviewModeEvent;
use codex_core::protocol::ListCustomPromptsResponseEvent;
@ -924,11 +925,19 @@ impl ChatWidget {
self.defer_or_handle(|q| q.push_exec_begin(ev), |s| s.handle_exec_begin_now(ev2));
}
fn on_exec_command_output_delta(
&mut self,
_ev: codex_core::protocol::ExecCommandOutputDeltaEvent,
) {
// TODO: Handle streaming exec output if/when implemented
fn on_exec_command_output_delta(&mut self, ev: ExecCommandOutputDeltaEvent) {
let Some(cell) = self
.active_cell
.as_mut()
.and_then(|c| c.as_any_mut().downcast_mut::<ExecCell>())
else {
return;
};
if cell.append_output(&ev.call_id, std::str::from_utf8(&ev.chunk).unwrap_or("")) {
self.bump_active_cell_revision();
self.request_redraw();
}
}
fn on_terminal_interaction(&mut self, _ev: TerminalInteractionEvent) {

View file

@ -125,6 +125,18 @@ impl ExecCell {
self.calls.iter()
}
pub(crate) fn append_output(&mut self, call_id: &str, chunk: &str) -> bool {
if chunk.is_empty() {
return false;
}
let Some(call) = self.calls.iter_mut().rev().find(|c| c.call_id == call_id) else {
return false;
};
let output = call.output.get_or_insert_with(CommandOutput::default);
output.aggregated_output.push_str(chunk);
true
}
pub(super) fn is_exploring_call(call: &ExecCall) -> bool {
!matches!(call.source, ExecCommandSource::UserShell)
&& !call.parsed.is_empty()