Use agent reply text in turn notifications (#3756)

Instead of "Agent turn complete", turn-complete notifications now
include the first handful of chars from the agent's final message.
This commit is contained in:
Jeremy Rose
2025-09-17 11:23:46 -07:00
committed by GitHub
parent 208089e58e
commit 530382db05

View File

@@ -255,7 +255,7 @@ impl ChatWidget {
self.request_redraw();
}
fn on_task_complete(&mut self) {
fn on_task_complete(&mut self, last_agent_message: Option<String>) {
// If a stream is currently active, finalize only that stream to flush any tail
// without emitting stray headers for other streams.
if self.stream.is_write_cycle_active() {
@@ -270,7 +270,9 @@ impl ChatWidget {
// If there is a queued user message, send exactly one now to begin the next turn.
self.maybe_send_next_queued_input();
// Emit a notification when the turn completes (suppressed if focused).
self.notify(Notification::AgentTurnComplete);
self.notify(Notification::AgentTurnComplete {
response: last_agent_message.unwrap_or_default(),
});
}
pub(crate) fn set_token_info(&mut self, info: Option<TokenUsageInfo>) {
@@ -1082,7 +1084,9 @@ impl ChatWidget {
}
EventMsg::AgentReasoningSectionBreak(_) => self.on_reasoning_section_break(),
EventMsg::TaskStarted(_) => self.on_task_started(),
EventMsg::TaskComplete(TaskCompleteEvent { .. }) => self.on_task_complete(),
EventMsg::TaskComplete(TaskCompleteEvent { last_agent_message }) => {
self.on_task_complete(last_agent_message)
}
EventMsg::TokenCount(ev) => self.set_token_info(ev.info),
EventMsg::Error(ErrorEvent { message }) => self.on_error(message),
EventMsg::TurnAborted(ev) => match ev.reason {
@@ -1479,7 +1483,7 @@ impl WidgetRef for &ChatWidget {
}
enum Notification {
AgentTurnComplete,
AgentTurnComplete { response: String },
ExecApprovalRequested { command: String },
EditApprovalRequested { cwd: PathBuf, changes: Vec<PathBuf> },
}
@@ -1487,7 +1491,10 @@ enum Notification {
impl Notification {
fn display(&self) -> String {
match self {
Notification::AgentTurnComplete => "Agent turn complete".to_string(),
Notification::AgentTurnComplete { response } => {
Notification::agent_turn_preview(response)
.unwrap_or_else(|| "Agent turn complete".to_string())
}
Notification::ExecApprovalRequested { command } => {
format!("Approval requested: {}", truncate_text(command, 30))
}
@@ -1507,7 +1514,7 @@ impl Notification {
fn type_name(&self) -> &str {
match self {
Notification::AgentTurnComplete => "agent-turn-complete",
Notification::AgentTurnComplete { .. } => "agent-turn-complete",
Notification::ExecApprovalRequested { .. }
| Notification::EditApprovalRequested { .. } => "approval-requested",
}
@@ -1519,8 +1526,26 @@ impl Notification {
Notifications::Custom(allowed) => allowed.iter().any(|a| a == self.type_name()),
}
}
fn agent_turn_preview(response: &str) -> Option<String> {
let mut normalized = String::new();
for part in response.split_whitespace() {
if !normalized.is_empty() {
normalized.push(' ');
}
normalized.push_str(part);
}
let trimmed = normalized.trim();
if trimmed.is_empty() {
None
} else {
Some(truncate_text(trimmed, AGENT_NOTIFICATION_PREVIEW_GRAPHEMES))
}
}
}
const AGENT_NOTIFICATION_PREVIEW_GRAPHEMES: usize = 200;
const EXAMPLE_PROMPTS: [&str; 6] = [
"Explain this codebase",
"Summarize recent commits",