use crate::{
output::{ActivityEvent, OutputEvent},
tui::{TuiEvent, send_best_effort, send_critical},
};
use crossbeam_channel::Sender;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(in crate::tui) enum EventDelivery {
Critical,
BestEffort,
}
pub(super) fn output_event_delivery(event: &OutputEvent) -> EventDelivery {
match event {
OutputEvent::AssistantDelta { .. } | OutputEvent::ThinkingSummaryDelta { .. } => {
EventDelivery::BestEffort
}
OutputEvent::SessionHeader { .. }
| OutputEvent::UserPrompt { .. }
| OutputEvent::AutomaticUserPrompt { .. }
| OutputEvent::CompactionTriggered { .. }
| OutputEvent::CompactionStarted
| OutputEvent::CompactionCompleted { .. }
| OutputEvent::BashCommand { .. }
| OutputEvent::ContextUsage { .. }
| OutputEvent::ThinkingSummaryComplete { .. }
| OutputEvent::ThinkingSummaryCompleteIdentified { .. }
| OutputEvent::AssistantComplete { .. }
| OutputEvent::Diagnostic { .. }
| OutputEvent::HookDiagnostic { .. }
| OutputEvent::ProviderContextInjection { .. }
| OutputEvent::SubdirInstructionInjection { .. }
| OutputEvent::ToolStarted { .. }
| OutputEvent::ToolResult { .. } => EventDelivery::Critical,
}
}
pub(super) fn activity_event_delivery(event: &ActivityEvent) -> EventDelivery {
match event {
ActivityEvent::Delta { .. } => EventDelivery::BestEffort,
ActivityEvent::Started { .. }
| ActivityEvent::UsageUpdate { .. }
| ActivityEvent::FinalPreview { .. }
| ActivityEvent::Finished { .. } => EventDelivery::Critical,
}
}
pub(in crate::tui) fn tui_event_delivery(event: &TuiEvent) -> EventDelivery {
match event {
TuiEvent::Output(event) => output_event_delivery(event),
TuiEvent::Activity(event) => activity_event_delivery(event),
TuiEvent::Error(_)
| TuiEvent::ModelCatalog { .. }
| TuiEvent::LoginInstructions(_)
| TuiEvent::LoginFinished { .. }
| TuiEvent::CompactionFinishedAuthoritative { .. }
| TuiEvent::Done
| TuiEvent::RunCanceled { .. }
| TuiEvent::RunFinished { .. }
| TuiEvent::SessionTitleUpdated { .. }
| TuiEvent::SessionPreviewLoaded { .. }
| TuiEvent::SessionSwitchLoaded { .. }
| TuiEvent::FooterGitBranchLoaded { .. }
| TuiEvent::StartupLoaded { .. }
| TuiEvent::UsageLoaded { .. } => EventDelivery::Critical,
}
}
pub(in crate::tui) fn send_tui_event(
sender: &Sender<TuiEvent>,
event: TuiEvent,
) -> anyhow::Result<()> {
match tui_event_delivery(&event) {
EventDelivery::Critical => send_critical(sender, event),
EventDelivery::BestEffort => {
send_best_effort(sender, event);
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::output::{ActivityId, ActivityMetadata, ActivityStatus};
#[test]
fn output_delivery_marks_streaming_deltas_best_effort() {
assert_eq!(
output_event_delivery(&OutputEvent::AssistantDelta { text: "x".into() }),
EventDelivery::BestEffort
);
assert_eq!(
output_event_delivery(&OutputEvent::AssistantComplete { text: "x".into() }),
EventDelivery::Critical
);
assert_eq!(
output_event_delivery(&OutputEvent::ThinkingSummaryDelta { text: "x".into() }),
EventDelivery::BestEffort
);
assert_eq!(
output_event_delivery(&OutputEvent::ThinkingSummaryComplete { text: "x".into() }),
EventDelivery::Critical
);
assert_eq!(
output_event_delivery(&OutputEvent::UserPrompt { text: "x".into() }),
EventDelivery::Critical
);
}
#[test]
fn activity_delivery_keeps_final_preview_critical() {
assert_eq!(
activity_event_delivery(&ActivityEvent::Delta {
id: ActivityId::new("tool-1"),
preview: "preview".into(),
}),
EventDelivery::BestEffort
);
assert_eq!(
activity_event_delivery(&ActivityEvent::FinalPreview {
id: ActivityId::new("tool-1"),
preview: "final".into(),
metadata: Some(ActivityMetadata::new("tool")),
status: Some(ActivityStatus::Success),
}),
EventDelivery::Critical
);
}
#[test]
fn tui_delivery_keeps_persistence_warning_critical() {
assert_eq!(
output_event_delivery(&OutputEvent::Diagnostic {
level: "warning".into(),
message: "session persistence failed; future resume may be incomplete".into(),
}),
EventDelivery::Critical
);
}
#[test]
fn tui_delivery_keeps_completion_and_errors_critical() {
assert_eq!(tui_event_delivery(&TuiEvent::Done), EventDelivery::Critical);
assert_eq!(
tui_event_delivery(&TuiEvent::Error("boom".into())),
EventDelivery::Critical
);
}
}