Repository navigation
Migrate bot-ready-signalling example to Pipecat client SDK - #209
Conversation
|
@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.
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.
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.
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>
- 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>
- .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>
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.
The rebase onto main hit two conflicts in bot-ready-signalling/server. pyproject.toml now keeps this branch's `runner` extra and takes main's `>=1.8.0` floor. It drops `fastapi[all]` and `uvicorn`, which only the deleted server.py used (the `runner` extra already pulls both in), and drops the `openai` extra, which nothing in the example imports. signalling_bot.py stays deleted; bot.py replaced it. Main moved signalling_bot.py to the 1.8.0 Workers API before this branch replaced that file, so bot.py gets the same change: PipelineTask becomes PipelineWorker, PipelineRunner becomes WorkerRunner, and the runner is built and given its worker before the event handlers. The old names still import in 1.8.x but only through deprecated shims that go away in 2.0.0. The test-demos CI job ran `uv run server.py`, a file this branch deleted. The demos.json entry now runs `uv run bot.py -t daily`, the same command the other runner-based demos use. `-t` is the runner's transport flag and `daily` is one of its choices. Also fix two stale lines in server/README.md that still pointed at server.py and the old /connect endpoint, and one README mention of PipelineTask.
d709585 to
ad76c66
Compare
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The README still described the old hand-written FastAPI server. The Pipecat runner replaced it, so three of the documented settings were wrong: - DAILY_SAMPLE_ROOM_URL is now DAILY_ROOM_URL, which is what the runner reads and what env.example already uses. - HOST and FAST_API_PORT are not read at all. The runner takes --host and --port, and defaults to localhost:7860. DAILY_API_URL stays, because the runner does still read it.
markbackman
left a comment
There was a problem hiding this comment.
Tagging @filipi87 to take a look. Not urgent.
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