Skip to content

feat: play notification sound on agent response#707

Open
hankkyy wants to merge 1 commit into
fathah:mainfrom
hankkyy:feat/notification-sound
Open

feat: play notification sound on agent response#707
hankkyy wants to merge 1 commit into
fathah:mainfrom
hankkyy:feat/notification-sound

Conversation

@hankkyy

@hankkyy hankkyy commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Feature

Play a short notification sound when the agent finishes responding, so users who switch away from the app know when an answer is ready.

Implementation

Uses the Web Audio API to generate a brief ascending two-tone beep (880 → 1100 Hz, 0.2 seconds, low volume). No external audio files needed.

The sound plays when isLoading transitions from true to false — indicating the agent has completed its response.

If AudioContext is unavailable or blocked (e.g., browser autoplay policy), the error is silently caught — the app continues normally.

Play a short ascending two-tone beep (Web Audio API) when the agent
completes a response, so users can switch away from the app and still
know when an answer is ready.

Changes:
- Chat: add useEffect watching isLoading transitions, generates a
  brief sine-wave beep (880→1100 Hz, 0.2s) using AudioContext.
  No external audio files needed. Fails silently if audio is blocked.
@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds a Web Audio API notification beep that fires when isLoading transitions from true to false, signalling the end of an agent response. No external audio files are required; the sound is synthesised inline.

  • AudioContext leak: a new AudioContext is created per response but never closed; browsers cap simultaneous instances (~6 in Chrome), so the feature silently stops working after a handful of chats.
  • Missing active guard: every other side-effecting handler in Chat checks active before firing, but the audio effect does not, causing background sessions to also beep when their agents finish.

Confidence Score: 3/5

Safe to merge as a non-breaking change, but the notification feature will silently stop working after a few responses and will fire for background sessions.

Two issues exist in the new code path: the AudioContext is never closed, so after roughly 6 responses the browser instance limit is hit and the beep silently stops working; and the missing active guard means background sessions also trigger audio, which is almost certainly unintended behaviour.

src/renderer/src/screens/Chat/Chat.tsx — the notification useEffect needs both an active guard and an osc.onended / ctx.close() call.

Important Files Changed

Filename Overview
src/renderer/src/screens/Chat/Chat.tsx Adds Web Audio API beep on agent response completion; the AudioContext is never closed (leaks past browser instance limit) and the active guard is missing (background sessions also beep).

Reviews (1): Last reviewed commit: "feat: play notification sound when agent..." | Re-trigger Greptile

Comment on lines +92 to +108
try {
const ctx = new AudioContext();
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.type = "sine";
// Play two quick ascending tones
osc.frequency.setValueAtTime(880, ctx.currentTime);
osc.frequency.setValueAtTime(1100, ctx.currentTime + 0.08);
gain.gain.setValueAtTime(0.12, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.2);
osc.start(ctx.currentTime);
osc.stop(ctx.currentTime + 0.2);
} catch {
// AudioContext may fail in some environments — silently ignore
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 AudioContext is never closed — stops working after a few responses. Browsers cap the number of simultaneously-live AudioContext instances (Chrome: ~6, Safari: lower). Each agent response allocates a new one that is never released, so after ~6 chats the constructor starts throwing and the sound silently stops working — exactly the regression users won't notice until it's been broken for a while.

Suggested change
try {
const ctx = new AudioContext();
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.type = "sine";
// Play two quick ascending tones
osc.frequency.setValueAtTime(880, ctx.currentTime);
osc.frequency.setValueAtTime(1100, ctx.currentTime + 0.08);
gain.gain.setValueAtTime(0.12, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.2);
osc.start(ctx.currentTime);
osc.stop(ctx.currentTime + 0.2);
} catch {
// AudioContext may fail in some environments — silently ignore
}
try {
const ctx = new AudioContext();
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.type = "sine";
// Play two quick ascending tones
osc.frequency.setValueAtTime(880, ctx.currentTime);
osc.frequency.setValueAtTime(1100, ctx.currentTime + 0.08);
gain.gain.setValueAtTime(0.12, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.2);
osc.start(ctx.currentTime);
osc.stop(ctx.currentTime + 0.2);
// Close the context once playback ends to avoid exhausting the browser limit
osc.onended = () => { void ctx.close(); };
} catch {
// AudioContext may fail in some environments — silently ignore
}

Comment on lines +85 to +90
// Play a notification sound when the agent finishes responding
const prevLoadingRef = useRef(isLoading);
useEffect(() => {
const wasLoading = prevLoadingRef.current;
prevLoadingRef.current = isLoading;
if (!wasLoading || isLoading) return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Sound fires for every mounted Chat instance, including background sessions. Every other audio/keyboard side effect in this component guards on active (see the Cmd+N handler, context-menu handlers, etc.), but the notification sound doesn't. If a user has two background sessions finishing simultaneously they'll both beep, and a background session finishing while the user is reading the active chat will emit a misleading sound.

Suggested change
// Play a notification sound when the agent finishes responding
const prevLoadingRef = useRef(isLoading);
useEffect(() => {
const wasLoading = prevLoadingRef.current;
prevLoadingRef.current = isLoading;
if (!wasLoading || isLoading) return;
// Play a notification sound when the agent finishes responding
const prevLoadingRef = useRef(isLoading);
useEffect(() => {
const wasLoading = prevLoadingRef.current;
prevLoadingRef.current = isLoading;
if (!wasLoading || isLoading) return;
if (!active) return;

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant