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:
@@ -255,7 +255,7 @@ impl ChatWidget {
|
|||||||
self.request_redraw();
|
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
|
// If a stream is currently active, finalize only that stream to flush any tail
|
||||||
// without emitting stray headers for other streams.
|
// without emitting stray headers for other streams.
|
||||||
if self.stream.is_write_cycle_active() {
|
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.
|
// If there is a queued user message, send exactly one now to begin the next turn.
|
||||||
self.maybe_send_next_queued_input();
|
self.maybe_send_next_queued_input();
|
||||||
// Emit a notification when the turn completes (suppressed if focused).
|
// 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>) {
|
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::AgentReasoningSectionBreak(_) => self.on_reasoning_section_break(),
|
||||||
EventMsg::TaskStarted(_) => self.on_task_started(),
|
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::TokenCount(ev) => self.set_token_info(ev.info),
|
||||||
EventMsg::Error(ErrorEvent { message }) => self.on_error(message),
|
EventMsg::Error(ErrorEvent { message }) => self.on_error(message),
|
||||||
EventMsg::TurnAborted(ev) => match ev.reason {
|
EventMsg::TurnAborted(ev) => match ev.reason {
|
||||||
@@ -1479,7 +1483,7 @@ impl WidgetRef for &ChatWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum Notification {
|
enum Notification {
|
||||||
AgentTurnComplete,
|
AgentTurnComplete { response: String },
|
||||||
ExecApprovalRequested { command: String },
|
ExecApprovalRequested { command: String },
|
||||||
EditApprovalRequested { cwd: PathBuf, changes: Vec<PathBuf> },
|
EditApprovalRequested { cwd: PathBuf, changes: Vec<PathBuf> },
|
||||||
}
|
}
|
||||||
@@ -1487,7 +1491,10 @@ enum Notification {
|
|||||||
impl Notification {
|
impl Notification {
|
||||||
fn display(&self) -> String {
|
fn display(&self) -> String {
|
||||||
match self {
|
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 } => {
|
Notification::ExecApprovalRequested { command } => {
|
||||||
format!("Approval requested: {}", truncate_text(command, 30))
|
format!("Approval requested: {}", truncate_text(command, 30))
|
||||||
}
|
}
|
||||||
@@ -1507,7 +1514,7 @@ impl Notification {
|
|||||||
|
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
Notification::AgentTurnComplete => "agent-turn-complete",
|
Notification::AgentTurnComplete { .. } => "agent-turn-complete",
|
||||||
Notification::ExecApprovalRequested { .. }
|
Notification::ExecApprovalRequested { .. }
|
||||||
| Notification::EditApprovalRequested { .. } => "approval-requested",
|
| Notification::EditApprovalRequested { .. } => "approval-requested",
|
||||||
}
|
}
|
||||||
@@ -1519,8 +1526,26 @@ impl Notification {
|
|||||||
Notifications::Custom(allowed) => allowed.iter().any(|a| a == self.type_name()),
|
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] = [
|
const EXAMPLE_PROMPTS: [&str; 6] = [
|
||||||
"Explain this codebase",
|
"Explain this codebase",
|
||||||
"Summarize recent commits",
|
"Summarize recent commits",
|
||||||
|
|||||||
Reference in New Issue
Block a user