-
Notifications
You must be signed in to change notification settings - Fork 175
Add support for away timeout #801
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add support for away timeout #801
Conversation
🦋 Changeset detectedLatest commit: 500a5f5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 14 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
| } | ||
|
|
||
| private _onUserInputTranscribed(ev: UserInputTranscribedEvent): void { | ||
| if (this.userState === 'away' && ev.isFinal) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we discard checking ev.isFinal? So we can turn away state back much quicker as soon as user starts speaking
| private _onUserInputTranscribed(ev: UserInputTranscribedEvent): void { | ||
| if (this.userState === 'away' && ev.isFinal) { | ||
| this.logger.debug('User returned from away state due to speech input'); | ||
| this._updateUserState('listening'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be "speaking"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re this and the above comment, happy to make this change.
I was however, trying to keep this in parity of the python implementation
Do you feel like we should still be adjusting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh I see, in this case let's keep this in parity with python.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a few comments, overall LGTM. cc @Shubhrakanti
Also, please create a changeset for this PR, thanks!
| const userPresenceTask = async (controller: AbortController): Promise<void> => { | ||
| for (let i = 0; i < 3; i++) { | ||
| if (controller.signal.aborted) return; | ||
|
|
||
| const reply = await session.generateReply({ | ||
| instructions: 'The user has been inactive. Politely check if the user is still present.', | ||
| }); | ||
|
|
||
| await reply.waitForPlayout(); | ||
|
|
||
| try { | ||
| await delay(10000, { signal: controller.signal }); | ||
| } catch { | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| if (!controller.signal.aborted) { | ||
| await session.close(); | ||
| } | ||
| }; | ||
|
|
||
| session.on(voice.AgentSessionEventTypes.UserStateChanged, (event) => { | ||
| logger.info({ event }, 'User state changed'); | ||
|
|
||
| if (task) { | ||
| task.cancel(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks pretty good!
Description
The framework didn't support the away state, so this PR adds support for this. I've done my best to document the logical paths of python ensuring to match verbatim here.
Changes Made
user_away_timeoutisNonenull || undefined, return earlyroom_io.subscribed_fut.done()isFalse!this.roomIO.isParticipantAvailableloop.call_later(timeout, callback)setTimeout(callback, timeout * 1000)_cancel_user_away_timer()_updateUserState()_set_user_away_timer()_updateUserState()_updateUserState()_updateAgentState()_updateAgentState()_updateAgentState()_user_input_transcribed()called withis_final=True_onUserInputTranscribed()withisFinal_user_input_transcribed()called withis_final=FalseisFinalaclose()called_aclose_impl()closeImpl()_set_user_away_timer()called multiple times_cancelUserAwayTimer()then set new_cancel_user_away_timer()called when no timer!== nullbefore clearing_update_user_state('away')_updateUserState('away')closeImpl()_onUserInputTranscribed()GMT20251104-174726_Clip_Paul.Heinrichs.s.Clip.11_04_2025.mp4
Pre-Review Checklist
Testing
restaurant_agent.tsandrealtime_agent.tswork properly (for major changes)Additional Notes
Notably the following shows up in my demo, but is related to the inference STT
Note to reviewers: Please ensure the pre-review checklist is completed before starting your review.