fix: send DTMF to active session room - #2010
Merged
Merged
Conversation
🦋 Changeset detectedLatest commit: 3bfaca6 The changes in this PR will be included in the next version bump. This PR includes changesets to release 36 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 |
Add deterministic coverage for room selection, event cadence, and publish failures while correcting the release level to patch. Co-authored-by: Cursor <cursoragent@cursor.com>
theomonnom
approved these changes
Jul 15, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
sendDtmfEventstool and export it through the beta namespace.AgentSessionRoomIO RTC room, falling back togetJobContext().roomwhen RoomIO is absent.Python parity
Ported from livekit/agents#6360 at Python head
0de254cd8114db4ee6122b9708ae041298640d8d.The source fix resolves
ctx.session.room_io.roomfirst and falls back to the job room when session RoomIO is unavailable. The JS adaptation usesctx.session._roomIO?.rtcRoom ?? getJobContext().room, milliseconds instead of seconds, androom.localParticipant.publishDtmf(code, digit). Because the target JS base did not yet contain Python's beta DTMF tool, this PR also ports the missing tool and beta exports.Deterministic coverage
agents/src/beta/tools/send_dtmf.test.tsproves:(1, "1"), (2, "2"), (11, "#")in order.The changeset is intentionally
patch: this ports/fixes beta behavior rather than introducing a stable breaking API.Validation
Passed on exact head
3bfaca6ffadad0f5de5225f460ded3d942a92450:pnpm test agents/src/beta/tools/send_dtmf.test.ts(3/3).pnpm build:agents.pnpm build.pnpm typecheck.pnpm lint.pnpm format:check.git diff --check.Broader pre-existing failures remain unrelated:
agents/src/voice/amd.test.tstiming/verdict cases, provider integration tests requiring available models, and API Extractor limitations/missing plugin configuration.Cue voice E2E
sid_de935ed216a0in fresh voice mode.3bfaca6ffadad0f5de5225f460ded3d942a92450, reconfirmed immediately before build and execution.debug_message(.payload.predicate="pr2010_exact_head_active_room_dtmf_verified",.payload.exactHead="3bfaca6ffadad0f5de5225f460ded3d942a92450").[(1,"1"), (2,"2"), (11,"#")]; job room[]; tool resultSuccessfully sent DTMF events: 1, 2, #;playoutComplete=true.~/.cue-cli/sessions/sid_de935ed216a0/recordings/001_run/result.json, SHA-2563ca75cf3725af45cf465a40c74c5dc3805185288d7aa2b8635e59b6576f4aa74.~/.cue-cli/sessions/sid_de935ed216a0/events.jsonl, SHA-2565253728e8140ccedd0fe13f7f10c0e0623b5e0cdab16acec4cd7efafdbd743c7.~/.cue-cli/sessions/sid_de935ed216a0/recording.wav— PCM 16-bit stereo/48 kHz, 15.0815 s, 2,895,692 bytes, SHA-256be43aad68025b81528e1b83cc1486f878f23e75c3755b1496834e0b38722d014; agent channel -27.0 dB mean, Cue channel silent.~/.cue-cli/sessions/sid_de935ed216a0/recordings/001_run/recording.wav— PCM 16-bit stereo/48 kHz, 8.389646 s, 1,610,856 bytes, SHA-2562f866d8748c8db6b1d2004a716cf281f624f0cc6f5bb6687a53142f999657c09; agent channel -24.5 dB mean, Cue channel silent.Boundary disclosure: Cue used a real LiveKit voice room and real Cartesia TTS playout. Warm-transfer separation used a deterministic controlled RTC-compatible boundary: the actual
beta.sendDtmfEventstool received a transferred-session RoomIO with a controlled active participant, while the real job-room participant publish boundary was intercepted independently. This proves exact room selection and emission without a SIP trunk or human supervisor; it is not a production telephony-provider call.Original PR description
The
send_dtmf_eventstool resolved the room from the job context, which is always the original caller room. During a warm transfer the tool runs in a separate session bound to a different room, so DTMF was published to the caller instead of the transferee.This resolves the room from the run context session (
ctx.session.room_io.room), falling back to the job context when the session has no room I/O.Fixes #6357