agent: Add sound notification when done generating (#31472)

This PR adds the ability to hear a sound notification when the agent is
done generating and/or needs user input. This setting is turned off by
default and can be used together with the visual notification. The
specific sound I'm using here comes from the [Material Design 2 Sound
Library](https://m2.material.io/design/sound/sound-resources.html#).

Release Notes:

- agent: Added the ability to have a sound notification when the agent
is done generating and/or needs user input.
This commit is contained in:
Danilo Leal 2025-05-26 21:20:41 -03:00 committed by GitHub
parent fe0bcd14d2
commit d211f88d23
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 93 additions and 5 deletions

View file

@ -16,6 +16,7 @@ use crate::ui::{
use anyhow::Context as _;
use assistant_settings::{AssistantSettings, NotifyWhenAgentWaiting};
use assistant_tool::ToolUseStatus;
use audio::{Audio, Sound};
use collections::{HashMap, HashSet};
use editor::actions::{MoveUp, Paste};
use editor::scroll::Autoscroll;
@ -996,9 +997,10 @@ impl ActiveThread {
}
ThreadEvent::Stopped(reason) => match reason {
Ok(StopReason::EndTurn | StopReason::MaxTokens) => {
let thread = self.thread.read(cx);
let used_tools = self.thread.read(cx).used_tools_since_last_user_message();
self.play_notification_sound(cx);
self.show_notification(
if thread.used_tools_since_last_user_message() {
if used_tools {
"Finished running tools"
} else {
"New message"
@ -1011,6 +1013,7 @@ impl ActiveThread {
_ => {}
},
ThreadEvent::ToolConfirmationNeeded => {
self.play_notification_sound(cx);
self.show_notification("Waiting for tool confirmation", IconName::Info, window, cx);
}
ThreadEvent::StreamedAssistantText(message_id, text) => {
@ -1147,6 +1150,13 @@ impl ActiveThread {
cx.notify();
}
fn play_notification_sound(&self, cx: &mut App) {
let settings = AssistantSettings::get_global(cx);
if settings.play_sound_when_agent_done {
Audio::play_sound(Sound::AgentDone, cx);
}
}
fn show_notification(
&mut self,
caption: impl Into<SharedString>,

View file

@ -327,6 +327,45 @@ impl AgentConfiguration {
)
}
fn render_sound_notification(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
let play_sound_when_agent_done =
AssistantSettings::get_global(cx).play_sound_when_agent_done;
h_flex()
.gap_4()
.justify_between()
.flex_wrap()
.child(
v_flex()
.gap_0p5()
.max_w_5_6()
.child(Label::new("Play sound when finished generating"))
.child(
Label::new(
"Hear a notification sound when the agent is done generating changes or needs your input.",
)
.color(Color::Muted),
),
)
.child(
Switch::new("play-sound-notification-switch", play_sound_when_agent_done.into())
.color(SwitchColor::Accent)
.on_click({
let fs = self.fs.clone();
move |state, _window, cx| {
let allow = state == &ToggleState::Selected;
update_settings_file::<AssistantSettings>(
fs.clone(),
cx,
move |settings, _| {
settings.set_play_sound_when_agent_done(allow);
},
);
}
}),
)
}
fn render_general_settings_section(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.p(DynamicSpacing::Base16.rems(cx))
@ -337,6 +376,7 @@ impl AgentConfiguration {
.child(Headline::new("General Settings"))
.child(self.render_command_permission(cx))
.child(self.render_single_file_review(cx))
.child(self.render_sound_notification(cx))
}
fn render_context_servers_section(