Migrate bot-ready-signalling example to Pipecat client SDK - #209
Conversation
Replace raw @daily-co/daily-js plumbing with @pipecat-ai/client-js plus
@pipecat-ai/daily-transport (web) and @pipecat-ai/react-native-daily-transport
(RN). The custom sendAppMessage("playable") workaround is removed in favour of
the standard RTVI client-ready / bot-ready handshake: RTVIProcessor is
auto-attached to PipelineTask, and the bot pushes the first TTSSpeakFrame from
@task.rtvi.event_handler("on_client_ready").
- Server: /connect now returns {url, token} (the shape DailyTransport expects).
signalling_bot.py drops the SilenceFrame workaround and on_app_message
handler, adds transport.input(), and queues the greeting from on_client_ready.
- JS client: rewritten around PipecatClient + DailyTransport with
startBotAndConnect; bot audio is rendered via the onTrackStarted callback.
- RN client: rewritten around PipecatClient + RNDailyTransport. Expo bumped
from 52 to 54 and RN to 0.81 to satisfy the transport's webrtc peer dep
(matches pipecat-examples/simple-chatbot).
- READMEs updated to describe the RTVI handshake.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add early-return in `connect()` so a second click while a client already exists does not orphan the previous PipecatClient and its listeners. - Align `@pipecat-ai/client-js` and `@pipecat-ai/daily-transport` to ^1.6.0 to match the React Native client. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…to ^1.6.1 Aligns both clients on the same client-js major and picks up the latest daily-transport patch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@pipecat-ai/daily-transport@1.6.1 requires @pipecat-ai/client-js@~1.7.0. The previous bump to ^1.8.0 broke npm install with ERESOLVE. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@filipi87 could you run a sanity test for the react native client? I haven't ran react native in a long time so all my dependencies are out of date 🙏 |
There was a problem hiding this comment.
Pull request overview
This PR modernizes the bot-ready-signalling example by migrating both web and React Native clients from direct @daily-co/* usage to the Pipecat client SDK + Daily transports, and by switching the example to the standard RTVI client-ready / bot-ready handshake to avoid clipped initial TTS audio.
Changes:
- Server:
/connectresponse shape updated to{url, token}and bot updated to trigger greeting fromon_client_ready. - Web client: rewritten around
PipecatClient+DailyTransport, rendering bot audio viaonTrackStarted. - RN client + docs: rewritten around
PipecatClient+RNDailyTransport, with READMEs updated to describe the RTVI handshake.
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| bot-ready-signalling/server/signalling_bot.py | Rewires bot to RTVI on_client_ready, adds transport input stage and enables audio-in. |
| bot-ready-signalling/server/server.py | Updates /connect return payload to {url, token} for Pipecat client SDK. |
| bot-ready-signalling/README.md | Documents the standard RTVI handshake and removes playable workaround mention. |
| bot-ready-signalling/client/javascript/src/app.js | Migrates browser client to PipecatClient + DailyTransport and plays audio via onTrackStarted. |
| bot-ready-signalling/client/javascript/index.html | Removes static <audio> element (now created dynamically). |
| bot-ready-signalling/client/javascript/README.md | Updates docs for Pipecat SDK + Daily transport and handshake explanation. |
| bot-ready-signalling/client/javascript/package.json | Replaces @daily-co/daily-js dependency with Pipecat SDK + Daily transport. |
| bot-ready-signalling/client/javascript/package-lock.json | Locks Pipecat SDK + Daily transport dependencies (brings in newer @daily-co/daily-js). |
| bot-ready-signalling/client/react-native/src/App.js | Migrates RN client to PipecatClient + RNDailyTransport with updated callbacks/logging. |
| bot-ready-signalling/client/react-native/README.md | Updates docs to explain RTVI bot-ready handshake. |
| bot-ready-signalling/client/react-native/package.json | Updates Expo/RN versions and swaps dependencies to Pipecat SDK + RN Daily transport. |
| bot-ready-signalling/client/react-native/app.json | Updates Expo config (plugins and new architecture flag). |
Files not reviewed (1)
- bot-ready-signalling/client/javascript/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- server: thread the meeting token from server.py through runner.configure into DailyTransport, instead of generating a second token in the bot and discarding it - js client: clear pcClient (and window.pcClient) on failed connect and on onDisconnected so reconnect works without a page reload - js client: document Node 22 requirement in README and add .nvmrc - rn client: clear clientRef.current on onDisconnected so remote disconnects don't wedge the Connect button - rn client: replace Yarn-only "resolutions" with npm "overrides" for the @daily-co/react-native-webrtc/debug pin Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 14 changed files in this pull request and generated 4 comments.
Files not reviewed (1)
- bot-ready-signalling/client/javascript/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- .nvmrc: pin to 22.14.0 (the actual minimum @daily-co/daily-js requires) rather than the major version, so `nvm use` selects a compatible runtime - README: tighten Node requirement text from "Node 22+" to ">=22.14.0" - js client: extract a useful string from onError messages (data.message, string data, or JSON.stringify) so users don't see "[object Object]" Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
I believe we could remove server.py and runner.py and just rely on the runner provided by Pipecat. In that case, we’d need to update signalling_bot.py to use it, like in other Pipecat examples. What do you think?
| await callObject.join({ url: roomInfo.room_url }); | ||
| log('Connecting to bot...'); | ||
| await client.startBotAndConnect({ | ||
| endpoint: `${API_BASE_URL}/connect`, |
There was a problem hiding this comment.
If we use the runner provided by Pipecat, this should be /start instead of /connect.
| }); | ||
|
|
||
| this.log('Connection complete'); | ||
| await this.pcClient.startBotAndConnect({ endpoint: '/connect' }); |
There was a problem hiding this comment.
Same here:
If we use the runner provided by Pipecat, this should be /start instead of /connect.
|
@jamsea, We should probably update |
filipi87
left a comment
There was a problem hiding this comment.
Looks good. I’ve pushed a fix for both RN and the environment variable name to use DAILY_ROOM_URL.
The only thing missing is refactoring to use the runner provided by Pipecat, but feel free to do that in a follow-up PR.
🚀
Replace the hand-rolled server.py + runner.py with `pipecat.runner.run`,
matching the canonical pattern in travel-companion / daily-custom-tracks.
Server is now started via `uv run bot.py -t daily` and exposes the standard
`/start` endpoint (Pipecat Cloud compatible).
JS and RN clients call `/start` with `{createDailyRoom: true}`. The Vite dev
proxy is updated from `/connect` to `/start`. Smoke-tested locally: POST
/start returns {dailyRoom, dailyToken, sessionId} and the bot joins.
Addresses filipi87's review on PR #209.
Summary
Replace the raw
@daily-co/daily-jsplumbing in thebot-ready-signallingexample with the Pipecat client SDK, and rewire the bot to use the standard RTVIclient-ready/bot-readyhandshake instead of the customsendAppMessage("playable")workaround.RTVIProcessoris auto-attached to everyPipelineTask, the JS/RN client SDKs signalclient-readyautomatically once the transport reaches thereadystate, and the bot pushes its firstTTSSpeakFramefrom@task.rtvi.event_handler("on_client_ready"). The current example predates these defaults and was misleading new users.What changed
Server
server/server.py:/connectnow returns{url, token}(the shapeDailyTransport.connect()expects).server/signalling_bot.py: dropSilenceFrameworkaround andon_app_message("playable")listener. Addtransport.input()andaudio_in_enabled=Trueso RTVI sees client messages. Queue the greeting fromon_client_ready.JS client (
client/javascript/)@daily-co/daily-jsfor@pipecat-ai/client-js+@pipecat-ai/daily-transport.src/app.js: rewrite aroundPipecatClient+DailyTransport. UsestartBotAndConnect({ endpoint: '/connect' }). Render bot audio via theonTrackStartedcallback.index.html: drop the static<audio>element.RN client (
client/react-native/)@daily-co/react-native-daily-js(direct import) and@config-plugins/react-native-webrtcfor@pipecat-ai/client-js+@pipecat-ai/react-native-daily-transport.^52→~54.0.21and RN0.76→0.81.5to satisfy the transport's@daily-co/react-native-webrtc@^124peer dep. Matches the canonicalpipecat-examples/simple-chatbotsetup.src/App.js: rewrite aroundPipecatClient+RNDailyTransport. Same UI shape (status bar, button, debug log).Docs
playablereferences.Test plan
cd server && uv sync && cp env.example .env, fillDAILY_API_KEY+CARTESIA_API_KEY, thenuv run server.py.cd client/javascript && npm install && npm run dev. Visithttp://localhost:5173, click Connect. Confirm transport state lands onready, the full greeting plays with no clipping, thebot-readylog fires before audio, and Disconnect cleans up.cd client/react-native && nvm i && npm install && npx expo prebuild --clean. SetAPI_BASE_URLin.env, thennpm run ios(ornpm run android). Tap Connect and run the same checks.🤖 Generated with Claude Code