in codex-rs/exec/src/event_processor_with_human_output.rs [227:366]
fn process_server_notification(&mut self, notification: ServerNotification) -> CodexStatus {
match notification {
ServerNotification::ConfigWarning(notification) => {
let details = notification
.details
.map(|details| format!(" ({details})"))
.unwrap_or_default();
eprintln!(
"{} {}{}",
"warning:".style(self.yellow).style(self.bold),
notification.summary,
details
);
CodexStatus::Running
}
ServerNotification::Error(notification) => {
eprintln!(
"{} {}",
"ERROR:".style(self.red).style(self.bold),
notification.error
);
CodexStatus::Running
}
ServerNotification::DeprecationNotice(notification) => {
eprintln!(
"{} {}",
"deprecated:".style(self.yellow).style(self.bold),
notification.summary
);
if let Some(details) = notification.details {
eprintln!("{}", details.style(self.dimmed));
}
CodexStatus::Running
}
ServerNotification::HookStarted(notification) => {
eprintln!(
"{} {}",
"hook:".style(self.bold),
format!("{:?}", notification.run.event_name).style(self.dimmed)
);
CodexStatus::Running
}
ServerNotification::HookCompleted(notification) => {
eprintln!(
"{} {} {:?}",
"hook:".style(self.bold),
format!("{:?}", notification.run.event_name).style(self.dimmed),
notification.run.status
);
CodexStatus::Running
}
ServerNotification::ItemStarted(notification) => {
self.render_item_started(¬ification.item);
CodexStatus::Running
}
ServerNotification::ItemCompleted(notification) => {
self.render_item_completed(notification.item);
CodexStatus::Running
}
ServerNotification::ModelRerouted(notification) => {
eprintln!(
"{} {} -> {}",
"model rerouted:".style(self.yellow).style(self.bold),
notification.from_model,
notification.to_model
);
CodexStatus::Running
}
ServerNotification::ModelVerification(_) => CodexStatus::Running,
ServerNotification::ThreadTokenUsageUpdated(notification) => {
self.last_total_token_usage = Some(notification.token_usage);
CodexStatus::Running
}
ServerNotification::TurnCompleted(notification) => match notification.turn.status {
TurnStatus::Completed => {
let rendered_message = self
.final_message_rendered
.then(|| self.final_message.clone())
.flatten();
if let Some(final_message) =
final_message_from_turn_items(notification.turn.items.as_slice())
{
self.final_message_rendered =
rendered_message.as_deref() == Some(final_message.as_str());
self.final_message = Some(final_message);
}
self.emit_final_message_on_shutdown = true;
CodexStatus::InitiateShutdown
}
TurnStatus::Failed => {
self.final_message = None;
self.final_message_rendered = false;
self.emit_final_message_on_shutdown = false;
if let Some(error) = notification.turn.error {
eprintln!("{} {}", "ERROR:".style(self.red).style(self.bold), error);
}
CodexStatus::InitiateShutdown
}
TurnStatus::Interrupted => {
self.final_message = None;
self.final_message_rendered = false;
self.emit_final_message_on_shutdown = false;
eprintln!("{}", "turn interrupted".style(self.dimmed));
CodexStatus::InitiateShutdown
}
TurnStatus::InProgress => CodexStatus::Running,
},
ServerNotification::TurnDiffUpdated(notification) => {
if !notification.diff.trim().is_empty() {
eprintln!("{}", notification.diff);
}
CodexStatus::Running
}
ServerNotification::TurnPlanUpdated(notification) => {
if let Some(explanation) = notification.explanation {
eprintln!("{}", explanation.style(self.italic));
}
for step in notification.plan {
match step.status {
codex_app_server_protocol::TurnPlanStepStatus::Completed => {
eprintln!(" {} {}", "✓".style(self.green), step.step);
}
codex_app_server_protocol::TurnPlanStepStatus::InProgress => {
eprintln!(" {} {}", "→".style(self.cyan), step.step);
}
codex_app_server_protocol::TurnPlanStepStatus::Pending => {
eprintln!(
" {} {}",
"•".style(self.dimmed),
step.step.style(self.dimmed)
);
}
}
}
CodexStatus::Running
}
ServerNotification::TurnStarted(_) => CodexStatus::Running,
_ => CodexStatus::Running,
}
}