Conversation
…ONY_STREAM Wire the telephony bridge that consumes the two already-merged #76 primitives (telephony-codec.ts transcode + twilio-mediastream.ts parse/build) into a real WebSocket route: wss://rt.wave.online/?room=<id>. INERT: fully gated behind WAVE_TELEPHONY_STREAM ([vars], default "0"). Off → maybeHandleTelephonyStream returns null and the request falls through to the existing 501 catch-all — the route is not registered and nothing changes. - src/telephony-ws.ts: pure TelephonyBridgeCore (injected I/O seams) + the route handler. INBOUND: parseTwilioFrame → twilioMuLawToSfuPcm → encodeIngestFrame on the SFU-dialed ingest socket (createIngestAdapter location:"local"). OUTBOUND: room 48k-stereo PCM → sfuPcmToTwilioMuLaw → twilioMediaFrame back over the WS. - Send-side framing default "packet", following rtms-bridge-core.ts / AgentSessionDO (every local-inject caller uses `framing ?? "packet"`). Marked TODO(live-spike) at the exact encodeIngestFrame call site — a live RoomDO inject may flip to "raw". - dispatch-helpers.ts: WAVE_TELEPHONY_STREAM env field + telephonyStreamEnabled(). - route-dispatch.ts: one delegation line (leaf-module pattern, file-size gate). - test/telephony-ws.test.ts: both-direction transcode byte-checks, framing override, drop-until-connected, start/createIngest, route guards. tsc clean; full suite green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_088d76b8-1f61-448a-817a-31c38fbdbf8e) |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 43 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Risk: medium. Not approving: Cursor Bugbot completed as skipped (usage limit reached) with no clean automated review, and gate/checks failed on src/route-dispatch.ts exceeding the 800-line limit. Human review is needed before merge; requested jfineman as reviewer.
Sent by Cursor Approval Agent: Pull Request Router and Approver
🌊 WAVE BugBot — 19 finding(s)🔴 16 · 🟠 3
severity: critical · major · minor · info — local review · $0 inference · wave-dispatch · react 👍/👎 to tune |


What this is
Wires the #76 Twilio Media-Stream ↔ WAVE room WebSocket bridge — the glue that finally consumes the two already-merged #76 primitives (
telephony-codec.tstranscode +twilio-mediastream.tsparse/build) into a real route:wss://rt.wave.online/?room=<id>.INERT — behind
WAVE_TELEPHONY_STREAM(default"0", OFF)When the flag is falsy/absent,
maybeHandleTelephonyStreamreturnsnulland a root?room=WS request falls through to the existing 501 catch-all — the route is not registered and no existing behavior changes. Arming it in any live env is a ◆ Jake crossing.What's built
src/telephony-ws.ts— a pureTelephonyBridgeCore(injected I/O seams → fully unit-testable, no live Twilio/SFU) plus the thin route handler. Mirrors the provenRtmsBridgeCore/AgentSessionDOinject pattern.parseTwilioFrame→twilioMuLawToSfuPcm(μ-law 8k mono → 48k stereo PCM) →encodeIngestFrameon the SFU-dialed ingest socket, published viacreateIngestAdapter(location:"local").sfuPcmToTwilioMuLaw→twilioMediaFrame→ sent back over the same WS.src/dispatch-helpers.ts—WAVE_TELEPHONY_STREAMenv field +telephonyStreamEnabled().src/route-dispatch.ts— one delegation line (leaf-module pattern, keeps the router under the file-size gate).wrangler.toml—WAVE_TELEPHONY_STREAM = "0"with the INERT/◆ rationale.test/telephony-ws.test.ts— both-direction transcode byte-for-byte against the pinned primitives, framing override, drop-until-connected, start/createIngestshape, and all route guard branches.Framing default
"packet"— the symmetric-with-the-verified-egress-decoder default every local-inject caller already uses (config.framing ?? "packet"inrtms-bridge-core.ts,agent-session.ts,agent-turn.ts). Followedrtms-bridge-core.ts(the closest analog: a media bridge thatcreateIngest(local)then sendsencodeIngestFrameon the SFU-dialed socket).The ONE remaining live-spike item (needs a human to dial in)
Marked
TODO(live-spike)at the exactencodeIngestFramecall site:"packet"vs"raw"is inherited fromagent-ingest-adapter.tsand is not yet proven against a live RoomDO inject. A real two-way phone call may flip it to"raw"(one config line, not a rewrite).null→ the bridge accepts + transcodes the call but publishes nothing (honest INERT, never a fabricated push).Verification
tsc --noEmit: clean.🤖 Generated with Claude Code
Note
Medium Risk
Default-off flag keeps prod unchanged, but arming exposes a root WebSocket ingress without gateway auth; SFU publish wiring is stubbed until the live spike.
Overview
Adds a Twilio Media-Stream ↔ WAVE room WebSocket bridge at
wss://rt.wave.online/?room=<id>, fully off by default viaWAVE_TELEPHONY_STREAM("0"inwrangler.toml).When armed,
TelephonyBridgeCoretranscodes caller μ-law → 48k stereo PCM into the existing SFU ingest path (createIngestAdapter+encodeIngestFrame) and room audio back to Twilio frames—same pattern as RTMS/agent ingest. The route is wired throughdispatch-helpers(telephonyStreamEnabled),route-dispatch, and newtelephony-ws.ts.Live spike still open: the handler uses
target: nullandingestSocket: () => null, so calls can connect and transcode but do not publish until room→session resolution, ingest endpoint minting, and auth are landed. The route is not behindgatewayGate(Twilio cannot sendx-wave-internal); signed stream tokens are called out as follow-up.test/telephony-ws.test.tscovers byte-exact transcode, framing, route guards, and flag gating.Reviewed by Cursor Bugbot for commit 231842f. Configure here.
Summary by cubic
Adds an inert Twilio Media-Stream ↔ room WebSocket bridge behind
WAVE_TELEPHONY_STREAM, exposingwss://rt.wave.online/?room=<id>to transcode audio and publish via the SFU ingest path. Progress on #76 using the existing transcode and Twilio frame primitives; off by default so nothing changes in production.New Features
src/telephony-ws.ts:TelephonyBridgeCoreand route handler. Inbound: parse → μ-law→PCM transcode →encodeIngestFrame. Outbound: room PCM → μ-law → Twiliomedia.WAVE_TELEPHONY_STREAMwithtelephonyStreamEnabled(); when off, the route falls through to the 501 catch-all.route-dispatch.ts;wrangler.tomlsets the flag to "0".test/telephony-ws.test.ts: both-direction transcode, framing override, drop-until-ingest, start/createIngest, and route guards.Migration
WAVE_TELEPHONY_STREAM="1"and provide SFU app creds; until room→session resolution and ingest endpoint minting land, frames drop until the SFU connects.Written for commit 231842f. Summary will update on new commits.