Skip to content

Migrate bot-ready-signalling example to Pipecat client SDK - #209

Merged
filipi87 merged 11 commits into
mainfrom
migrate-bot-ready-signalling-to-pipecat-client-js
Sep 23, 2026
Merged

filipi87 merged 11 commits into
mainfrom
migrate-bot-ready-signalling-to-pipecat-client-js

Conversation

@jamsea

@jamsea jamsea commented May 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Replace the raw @daily-co/daily-js plumbing in the bot-ready-signalling example with the Pipecat client SDK, and rewire the bot to use the standard RTVI client-ready / bot-ready handshake instead of the custom sendAppMessage("playable") workaround.

RTVIProcessor is auto-attached to every PipelineTask, the JS/RN client SDKs signal client-ready automatically once the transport reaches the ready state, and the bot pushes its first TTSSpeakFrame from @task.rtvi.event_handler("on_client_ready"). The current example predates these defaults and was misleading new users.

What changed

Server

  • server/server.py: /connect now returns {url, token} (the shape DailyTransport.connect() expects).
  • server/signalling_bot.py: drop SilenceFrame workaround and on_app_message("playable") listener. Add transport.input() and audio_in_enabled=True so RTVI sees client messages. Queue the greeting from on_client_ready.

JS client (client/javascript/)

  • Swap @daily-co/daily-js for @pipecat-ai/client-js + @pipecat-ai/daily-transport.
  • src/app.js: rewrite around PipecatClient + DailyTransport. Use startBotAndConnect({ endpoint: '/connect' }). Render bot audio via the onTrackStarted callback.
  • index.html: drop the static <audio> element.

RN client (client/react-native/)

  • Swap @daily-co/react-native-daily-js (direct import) and @config-plugins/react-native-webrtc for @pipecat-ai/client-js + @pipecat-ai/react-native-daily-transport.
  • Bump Expo ^52 → ~54.0.21 and RN 0.76 → 0.81.5 to satisfy the transport's @daily-co/react-native-webrtc@^124 peer dep. Matches the canonical pipecat-examples/simple-chatbot setup.
  • src/App.js: rewrite around PipecatClient + RNDailyTransport. Same UI shape (status bar, button, debug log).

Docs

  • Top-level + JS + RN READMEs describe the RTVI handshake and drop playable references.

Test plan

  • cd server && uv sync && cp env.example .env, fill DAILY_API_KEY + CARTESIA_API_KEY, then uv run server.py.
  • JS client: cd client/javascript && npm install && npm run dev. Visit http://localhost:5173, click Connect. Confirm transport state lands on ready, the full greeting plays with no clipping, the bot-ready log fires before audio, and Disconnect cleans up.
  • RN client: cd client/react-native && nvm i && npm install && npx expo prebuild --clean. Set API_BASE_URL in .env, then npm run ios (or npm run android). Tap Connect and run the same checks.

🤖 Generated with Claude Code

@jamsea
jamsea requested a review from Copilot May 5, 2026 07:11
@jamsea
jamsea requested a review from filipi87 May 5, 2026 07:13
@jamsea

jamsea commented May 5, 2026

Copy link
Copy Markdown
Contributor Author

@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 🙏

@jamsea
jamsea marked this pull request as ready for review May 5, 2026 07:14
@jamsea
jamsea requested a review from markbackman May 5, 2026 07:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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: /connect response shape updated to {url, token} and bot updated to trigger greeting from on_client_ready.
  • Web client: rewritten around PipecatClient + DailyTransport, rendering bot audio via onTrackStarted.
  • 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.

Comment thread bot-ready-signalling/server/signalling_bot.py Outdated
Comment thread bot-ready-signalling/client/javascript/src/app.js
Comment thread bot-ready-signalling/client/javascript/src/app.js
Comment thread bot-ready-signalling/client/react-native/src/App.js
Comment thread bot-ready-signalling/client/javascript/package-lock.json
Comment thread bot-ready-signalling/client/react-native/package.json Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread bot-ready-signalling/client/javascript/README.md Outdated
Comment thread bot-ready-signalling/client/javascript/.nvmrc Outdated
Comment thread bot-ready-signalling/client/javascript/src/app.js Outdated
Comment thread bot-ready-signalling/client/react-native/package.json
Comment thread bot-ready-signalling/server/server.py Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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' });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here:
If we use the runner provided by Pipecat, this should be /start instead of /connect.

@filipi87

filipi87 commented May 5, 2026

Copy link
Copy Markdown
Contributor

@jamsea, We should probably update env.example and the README as well. What we previously referred to as DAILY_SAMPLE_ROOM_URL is now just DAILY_ROOM_URL.

@filipi87 filipi87 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

🚀

jamsea added a commit that referenced this pull request May 6, 2026
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.
jamsea and others added 10 commits September 22, 2026 15:20
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.
@jamsea
jamsea force-pushed the migrate-bot-ready-signalling-to-pipecat-client-js branch from d709585 to ad76c66 Compare September 22, 2026 07:25
@vercel

vercel Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
pipecat-examples Ready Ready Preview Sep 22, 2026 7:34am UTC

Request Review

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 markbackman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagging @filipi87 to take a look. Not urgent.

@filipi87 filipi87 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice clean up. 🚀

@filipi87
filipi87 merged commit 93c0bd5 into main Sep 23, 2026
47 checks passed

This branch was successfully deployed

1 active deployment
Preview — 7e4e27c9 Deployed Sep 22, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants