Skip to content

feat(voice/avatar): kick avatar participant on aclose + wait_for_join helper#5836

Merged
theomonnom merged 3 commits into
mainfrom
feat/avatar-base-aclose-remove-participant
May 25, 2026
Merged

feat(voice/avatar): kick avatar participant on aclose + wait_for_join helper#5836
theomonnom merged 3 commits into
mainfrom
feat/avatar-base-aclose-remove-participant

Conversation

@theomonnom
Copy link
Copy Markdown
Member

@theomonnom theomonnom commented May 25, 2026

No description provided.

…join

BaseAvatarSession.aclose() now calls RoomService.RemoveParticipant on
its avatar identity before tearing down its own state, so the avatar's
audio + video tracks unpublish synchronously instead of lingering until
the upstream provider notices the client is gone. Surfaces failures
at warning level β€” a stuck avatar participant is worth seeing in logs.

Adds BaseAvatarSession.wait_for_join() so provider implementations can
let callers await actual avatar presence (participant + video track)
from start(), and a timeout kwarg on utils.wait_for_participant /
wait_for_track_publication so wait_for_join can be bounded.
@chenghao-mou chenghao-mou requested a review from a team May 25, 2026 05:04
…ck_publication

wait_for_join bounds itself with asyncio.wait_for on the task, so the
plumbed-through timeout kwarg on the util functions is dead code.
Drop the prescriptive 'providers should call this from start()' note β€”
that's an integration choice for the LemonSlice example, not part of
the public contract.
@theomonnom theomonnom merged commit 69a626f into main May 25, 2026
21 of 23 checks passed
@theomonnom theomonnom deleted the feat/avatar-base-aclose-remove-participant branch May 25, 2026 05:10
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review

Comment on lines +122 to +123
if self._wait_avatar_join_task is None:
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.

πŸ”΄ wait_for_join silently returns before avatar joins when room is not yet connected

When start() is called with a disconnected room (lines 110-113), _wait_avatar_join_task is not created immediately β€” only a connection_state_changed listener is registered. The task is created later in _on_connection_state_changed (line 203-204) when the room actually connects. However, wait_for_join() at line 122-123 returns immediately if _wait_avatar_join_task is None, which silently signals success to the caller even though the avatar has not joined. This violates the method's documented contract to "wait until the avatar participant has joined the room and published its video track."

Prompt for agents
The wait_for_join method returns immediately when _wait_avatar_join_task is None, but this state occurs legitimately when start() was called with a disconnected room (the task is only created later by _on_connection_state_changed). The fix should make wait_for_join able to wait for the task to be created. One approach: introduce an asyncio.Event (e.g. self._avatar_joined_event) that is set at the end of _wait_avatar_join(), and have wait_for_join await that event (with the specified timeout) instead of directly awaiting the task. This handles both the connected and not-yet-connected cases correctly. Alternatively, you could make the task always created in start() (even for disconnected rooms, the task itself would first wait for connection).
Open in Devin Review

Was this helpful? React with πŸ‘ or πŸ‘Ž to provide feedback.

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.

2 participants