* fix(agent): end the reply quietly when the caller has left the call
socketedge.ErrLeft now wraps agent.ErrCallLeft, and both publish paths
log it at debug instead of an ERROR "agent failure" (AI-1866).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(api): close session and dispatch sockets with a close frame
An unreadable frame is answered with an error frame and 1008, and a
session closed by its socket's close command ends with 1000 (AI-1441).
socket.end's close-and-drain is now closeSocket, shared by both.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(api): wait for the socket's session before speaking into its voice
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* AI-1441: Log a left call's dropped audio once per reply, and assert it
The suite now logs at debug and counts the line: once per synthesis, once per
response id, not once per chunk.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* AI-1441: The Stream edge's left call is agent.ErrCallLeft
Closing the agent mid-reply logged an ERROR for each buffered chunk.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* AI-1441: Say a session socket ends on an unreadable frame; time the caller-close wait
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>