Skip to content

feat(pipecat): upgrade pipecat-ai 1.1.0 → 1.5.0, daily-python 0.28 → 0.30#892

Open
swaroopvarma1 wants to merge 1 commit into
releasefrom
feat/pipecat-1.5-upgrade
Open

feat(pipecat): upgrade pipecat-ai 1.1.0 → 1.5.0, daily-python 0.28 → 0.30#892
swaroopvarma1 wants to merge 1 commit into
releasefrom
feat/pipecat-1.5-upgrade

Conversation

@swaroopvarma1

Copy link
Copy Markdown
Collaborator

Why

Part 2 of the widget Daily voice-mode crackling fix (part 1: #891). Our pinned pipecat 1.1.0 + daily-python 0.28.0 are missing a series of upstream audio-quality and stability fixes shipped through 1.5.0:

Fix Version
SOXR resampler quality setting actually applied (#4551) 1.3.0
BaseOutputTransport no longer reorders frames with equal PTS 1.3.0
200–300 ms audible mixer gap on every interruption fixed 1.4.0
SOXRStreamAudioResampler clears stale state after gaps (#4886) 1.5.0
daily-python audio playout thread use-after-free/segfault fixes 0.29.x/0.30.0

Migration (1.1.0 → 1.5.0)

  • pipecat-ai-flows removed — upstream deprecated/froze the standalone package; Flows now ships inside pipecat-ai as pipecat.flows with the same API. All pipecat_flows imports rewritten.
  • Typed CallDataparse_telephony_websocket returns a dict-compatible Pydantic model; inbound/IVR/transfer signatures retyped dictCallData (runtime .get()/[] access unchanged).
  • FunctionCallParams.pipeline_worker (new required field) — MCP synthetic params pass None, same contract as the existing llm/context fields (never read by MCPClient._tool_wrapper).
  • AnthropicLLMAdapter.get_llm_invocation_params now requires enable_prompt_caching — observers pass False (one-shot calls).
  • Settings possibly NOT_GIVEN — chat llm_driver narrows system_instruction to str | None.
  • FlowManager(task=…) deprecatedworker= (same object).
  • FlowsFunctionSchema.handler now required — app code always passed it; test stub updated.

Inherited behavior changes (intentional, reviewed)

  • TTSSpeakFrame.append_to_context now defaults True: agent-mode greetings/fillers are recorded in the LLM context (previously situation-dependent). Widget stream mode has no assistant aggregator → unaffected.
  • Flows' initial node follows its context strategy (APPEND default) instead of always replacing — pre-inference greeting context is preserved.
  • RTVI protocol bumped to 2.0.0 server-side; 1.x JS clients (our widget/dashboard) are explicitly served the legacy format per upstream, no client upgrade required.

Verified

  • uv run pyrefly check — 0 errors
  • uv run pytest574 passed, 1 xfailed
  • All breeze_buddy voice/chat/MCP/daily modules import cleanly on 1.5.0
  • Daily keepalive monkeypatch surface (DailyTransportClient.leave/cleanup/_leave/_cleanup) verified present in 1.5.0
  • AICFilter(license_key=…, model_path=…) signature unchanged

Follow-ups

  • Beta verify: AIC noise-filter model files against aic-sdk 2.5.0 (init is fail-open — worst case the filter is skipped with a warning). Only affects templates with noise_filter.enable.
  • Upstream #4993 (trailing TTS chunk flush) merged post-1.5.0 — pick it up on the next release; pairs with fix(daily): raise audio_out_10ms_chunks to 100ms to stop bot-voice crackling #891's larger output chunks.
  • Manual E2E on beta: telephony call (Twilio/Plivo/Exotel), warm transfer, widget voice + chat session.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JMS9AtnyXQXHADd1ca1TwK

…> 0.30

Motivated by the widget Daily voice-mode crackling investigation: 1.1.0 is
missing a series of upstream audio-quality fixes shipped in 1.2.x-1.5.0.
This bump picks up:
- SOXR resampler quality setting actually applied (1.3.0, upstream #4551)
- BaseOutputTransport no longer reorders frames with equal PTS (1.3.0)
- 200-300ms audible mixer gap on interruption fixed (1.4.0)
- SOXRStreamAudioResampler clears stale state after gaps (1.5.0, #4886)
- daily-python 0.30.0: audio playout thread use-after-free/segfault fixes,
  virtual-mic publishing segfault fix (0.28.1)

Migration notes:
- pipecat-ai-flows is deprecated/frozen upstream and now ships inside
  pipecat-ai as pipecat.flows (same API). Dependency removed; all
  pipecat_flows imports rewritten to pipecat.flows.
- parse_telephony_websocket now returns a typed, dict-compatible CallData
  model: inbound/IVR/transfer signatures retyped dict -> CallData
  (runtime .get()/[] access unchanged).
- FunctionCallParams grew a required pipeline_worker field: the MCP
  synthetic-params construction passes None like the existing llm/context.
- AnthropicLLMAdapter.get_llm_invocation_params requires
  enable_prompt_caching: observers pass False (one-shot calls).
- LLM settings values are now typed possibly-NOT_GIVEN: chat llm_driver
  narrows system_instruction to str | None before adapter calls.
- FlowManager task= kwarg deprecated: switched to worker= (same object).
- FlowsFunctionSchema.handler is now required (app code always passed it;
  test stub updated).

Behavior changes inherited (intentional):
- TTSSpeakFrame.append_to_context defaults to True: agent-mode greetings /
  fillers are now recorded in the LLM context. Stream mode (widget voice)
  has no assistant aggregator, so it is unaffected.
- Flows initial node follows its context strategy (APPEND default) instead
  of always replacing: pre-inference greeting text is preserved.

Verified: pyrefly 0 errors; 574 passed, 1 xfailed; all breeze_buddy voice
modules import cleanly on 1.5.0. Follow-up for beta: re-verify AIC noise
filter model files against aic-sdk 2.5.0 (fail-open if incompatible).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JMS9AtnyXQXHADd1ca1TwK
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@swaroopvarma1, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: df4ee7f2-2b66-4184-9fc1-2e45d6b638bb

📥 Commits

Reviewing files that changed from the base of the PR and between 03e0c98 and 7b734c7.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • app/ai/voice/agents/breeze_buddy/agent/__init__.py
  • app/ai/voice/agents/breeze_buddy/agent/flow.py
  • app/ai/voice/agents/breeze_buddy/agent/inbound.py
  • app/ai/voice/agents/breeze_buddy/chat/agent.py
  • app/ai/voice/agents/breeze_buddy/chat/llm_driver.py
  • app/ai/voice/agents/breeze_buddy/ivr/selection.py
  • app/ai/voice/agents/breeze_buddy/mcp/__init__.py
  • app/ai/voice/agents/breeze_buddy/observers/llm.py
  • app/ai/voice/agents/breeze_buddy/template/builder.py
  • app/ai/voice/agents/breeze_buddy/template/context.py
  • app/ai/voice/agents/breeze_buddy/template/global_function.py
  • app/ai/voice/agents/breeze_buddy/utils/agent_transfer.py
  • pyproject.toml
  • tests/test_chat_gate_partition.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/pipecat-1.5-upgrade

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

swaroopvarma1 pushed a commit that referenced this pull request Jul 14, 2026
Part 3 of the widget voice crackle fix (after #891 chunk sizing and #892
pipecat 1.5.0). Daily bots ran via asyncio.create_task inside the
single-worker FastAPI process, so the 10ms-paced audio writer competed with
every HTTP request, chat turn, and other call on one event loop — the root
cause of intermittent agent-voice crackling (underruns concealed by the
browser as glitches). A native daily-python crash could also take down the
whole API pod.

start_daily_session now spawns services/daily/bot_runner.py as a per-call
OS process running the exact same daily_bot code path. Gated by the
BB_DAILY_BOT_SUBPROCESS dynamic config (DevCycle/Redis -> env -> default),
DEFAULT ON; flipping it to false is the no-restart escape hatch back to
the legacy in-process launch (affects new calls only).

- The launch payload (room_url, token, lead/session ids) travels over
  stdin, never argv, so the Daily token is not visible in `ps`.
- The child inherits the environment, with POSTGRES_POOL_SIZE=1 /
  POSTGRES_MAX_OVERFLOW=2 overrides (init_db_pool eagerly opens
  min_size connections; a per-call child must not open the API pod's
  full pool). Override via BB_VOICE_BOT_DB_POOL_SIZE /
  BB_VOICE_BOT_DB_MAX_OVERFLOW.
- Child stdout/stderr are inherited, so its loguru output (same
  colored-dev / JSON-prod config, driven by the inherited ENVIRONMENT)
  lands in the same container log stream; log context (lead_id,
  call_sid, conversation_id) is set inside the bot exactly as before.
- A log-only reaper records the child's exit code; dead-bot recovery
  stays with the existing safety nets (/voice/end crash-net channel
  flip, 1h room expiry) — identical to a dead in-process task before.

No functionality changes: every bot<->API coordination path is already
process-agnostic (DB writes, the cross-process Redis session lock,
DB-backed approvals, the Daily room itself), and every resource the bot
needs is a lazy singleton (asyncpg pool, Redis) or env-driven. Applies
uniformly to widget DAILY_STREAM, demo, and dashboard daily bots.

Known deltas: bot join gains ~2-3s (child interpreter + imports; warm
pool is a follow-up if it matters), each call adds one process (own ONNX
copies) and 1-3 Postgres connections — size pods accordingly.

Verified: pyrefly 0 errors; 583 passed, 1 xfailed (9 new tests: stdin
payload round-trip incl. child-side parse, spawn args/env/stdin
contract, escape-hatch fallback to in-process); bot_runner smoke-tested
via `python -m` (invalid payload exits 2 with a clean error log).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JMS9AtnyXQXHADd1ca1TwK
swaroopvarma1 pushed a commit that referenced this pull request Jul 14, 2026
Part 3 of the widget voice crackle fix (after #891 chunk sizing and #892
pipecat 1.5.0). Daily bots ran via asyncio.create_task inside the
single-worker FastAPI process, so the 10ms-paced audio writer competed with
every HTTP request, chat turn, and other call on one event loop — the root
cause of intermittent agent-voice crackling (underruns concealed by the
browser as glitches). A native daily-python crash could also take down the
whole API pod.

start_daily_session now spawns services/daily/bot_runner.py as a per-call
OS process running the exact same daily_bot code path. Gated by the
BB_DAILY_BOT_SUBPROCESS dynamic config (DevCycle/Redis -> env -> default),
DEFAULT ON; flipping it to false is the no-restart escape hatch back to
the legacy in-process launch (affects new calls only).

- The launch payload (room_url, token, lead/session ids) travels over
  stdin, never argv, so the Daily token is not visible in `ps`.
- The child inherits the environment, with POSTGRES_POOL_SIZE=1 /
  POSTGRES_MAX_OVERFLOW=2 overrides (init_db_pool eagerly opens
  min_size connections; a per-call child must not open the API pod's
  full pool). Override via BB_VOICE_BOT_DB_POOL_SIZE /
  BB_VOICE_BOT_DB_MAX_OVERFLOW.
- Child stdout/stderr are inherited, so its loguru output (same
  colored-dev / JSON-prod config, driven by the inherited ENVIRONMENT)
  lands in the same container log stream; log context (lead_id,
  call_sid, conversation_id) is set inside the bot exactly as before.
- A log-only reaper records the child's exit code; dead-bot recovery
  stays with the existing safety nets (/voice/end crash-net channel
  flip, 1h room expiry) — identical to a dead in-process task before.

No functionality changes: every bot<->API coordination path is already
process-agnostic (DB writes, the cross-process Redis session lock,
DB-backed approvals, the Daily room itself), and every resource the bot
needs is a lazy singleton (asyncpg pool, Redis) or env-driven. Applies
uniformly to widget DAILY_STREAM, demo, and dashboard daily bots.

Known deltas: bot join gains ~2-3s (child interpreter + imports; warm
pool is a follow-up if it matters), each call adds one process (own ONNX
copies) and 1-3 Postgres connections — size pods accordingly.

Verified: pyrefly 0 errors; 583 passed, 1 xfailed (9 new tests: stdin
payload round-trip incl. child-side parse, spawn args/env/stdin
contract, escape-hatch fallback to in-process); bot_runner smoke-tested
via `python -m` (invalid payload exits 2 with a clean error log).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JMS9AtnyXQXHADd1ca1TwK
swaroopvarma1 pushed a commit that referenced this pull request Jul 14, 2026
Part 3 of the widget voice crackle fix (after #891 chunk sizing and #892
pipecat 1.5.0). Daily bots ran via asyncio.create_task inside the
single-worker FastAPI process, so the 10ms-paced audio writer competed with
every HTTP request, chat turn, and other call on one event loop — the root
cause of intermittent agent-voice crackling (underruns concealed by the
browser as glitches). A native daily-python crash could also take down the
whole API pod.

start_daily_session now spawns services/daily/bot_runner.py as a per-call
OS process running the exact same daily_bot code path. Gated by the
BB_DAILY_BOT_SUBPROCESS dynamic config (DevCycle/Redis -> env -> default),
DEFAULT ON; flipping it to false is the no-restart escape hatch back to
the legacy in-process launch (affects new calls only).

- The launch payload (room_url, token, lead/session ids) travels over
  stdin, never argv, so the Daily token is not visible in `ps`.
- The child inherits the environment, with POSTGRES_POOL_SIZE=1 /
  POSTGRES_MAX_OVERFLOW=2 overrides (init_db_pool eagerly opens
  min_size connections; a per-call child must not open the API pod's
  full pool). Override via BB_VOICE_BOT_DB_POOL_SIZE /
  BB_VOICE_BOT_DB_MAX_OVERFLOW.
- Child stdout/stderr are inherited, so its loguru output (same
  colored-dev / JSON-prod config, driven by the inherited ENVIRONMENT)
  lands in the same container log stream; log context (lead_id,
  call_sid, conversation_id) is set inside the bot exactly as before.
- A log-only reaper records the child's exit code; dead-bot recovery
  stays with the existing safety nets (/voice/end crash-net channel
  flip, 1h room expiry) — identical to a dead in-process task before.

No functionality changes: every bot<->API coordination path is already
process-agnostic (DB writes, the cross-process Redis session lock,
DB-backed approvals, the Daily room itself), and every resource the bot
needs is a lazy singleton (asyncpg pool, Redis) or env-driven. Applies
uniformly to widget DAILY_STREAM, demo, and dashboard daily bots.

Known deltas: bot join gains ~2-3s (child interpreter + imports; warm
pool is a follow-up if it matters), each call adds one process (own ONNX
copies) and 1-3 Postgres connections — size pods accordingly.

Verified: pyrefly 0 errors; 583 passed, 1 xfailed (9 new tests: stdin
payload round-trip incl. child-side parse, spawn args/env/stdin
contract, escape-hatch fallback to in-process); bot_runner smoke-tested
via `python -m` (invalid payload exits 2 with a clean error log).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JMS9AtnyXQXHADd1ca1TwK
swaroopvarma1 pushed a commit that referenced this pull request Jul 14, 2026
Part 3 of the widget voice crackle fix (after #891 chunk sizing and #892
pipecat 1.5.0). Daily bots ran via asyncio.create_task inside the
single-worker FastAPI process, so the 10ms-paced audio writer competed with
every HTTP request, chat turn, and other call on one event loop — the root
cause of intermittent agent-voice crackling (underruns concealed by the
browser as glitches). A native daily-python crash could also take down the
whole API pod.

start_daily_session now spawns services/daily/bot_runner.py as a per-call
OS process running the exact same daily_bot code path. Gated by the
BB_DAILY_BOT_SUBPROCESS dynamic config (DevCycle/Redis -> env -> default),
DEFAULT ON; flipping it to false is the no-restart escape hatch back to
the legacy in-process launch (affects new calls only).

- The launch payload (room_url, token, lead/session ids) travels over
  stdin, never argv, so the Daily token is not visible in `ps`.
- The child inherits the environment, with POSTGRES_POOL_SIZE=1 /
  POSTGRES_MAX_OVERFLOW=2 overrides (init_db_pool eagerly opens
  min_size connections; a per-call child must not open the API pod's
  full pool). Override via BB_VOICE_BOT_DB_POOL_SIZE /
  BB_VOICE_BOT_DB_MAX_OVERFLOW.
- Child stdout/stderr are inherited, so its loguru output (same
  colored-dev / JSON-prod config, driven by the inherited ENVIRONMENT)
  lands in the same container log stream; log context (lead_id,
  call_sid, conversation_id) is set inside the bot exactly as before.
- A log-only reaper records the child's exit code; dead-bot recovery
  stays with the existing safety nets (/voice/end crash-net channel
  flip, 1h room expiry) — identical to a dead in-process task before.

No functionality changes: every bot<->API coordination path is already
process-agnostic (DB writes, the cross-process Redis session lock,
DB-backed approvals, the Daily room itself), and every resource the bot
needs is a lazy singleton (asyncpg pool, Redis) or env-driven. Applies
uniformly to widget DAILY_STREAM, demo, and dashboard daily bots.

Known deltas: bot join gains ~2-3s (child interpreter + imports; warm
pool is a follow-up if it matters), each call adds one process (own ONNX
copies) and 1-3 Postgres connections — size pods accordingly.

Verified: pyrefly 0 errors; 583 passed, 1 xfailed (9 new tests: stdin
payload round-trip incl. child-side parse, spawn args/env/stdin
contract, escape-hatch fallback to in-process); bot_runner smoke-tested
via `python -m` (invalid payload exits 2 with a clean error log).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JMS9AtnyXQXHADd1ca1TwK
swaroopvarma1 pushed a commit that referenced this pull request Jul 14, 2026
Part 3 of the widget voice crackle fix (after #891 chunk sizing and #892
pipecat 1.5.0). Daily bots ran via asyncio.create_task inside the
single-worker FastAPI process, so the 10ms-paced audio writer competed with
every HTTP request, chat turn, and other call on one event loop — the root
cause of intermittent agent-voice crackling (underruns concealed by the
browser as glitches). A native daily-python crash could also take down the
whole API pod.

start_daily_session now spawns services/daily/bot_runner.py as a per-call
OS process running the exact same daily_bot code path. Gated by the
BB_DAILY_BOT_SUBPROCESS dynamic config (DevCycle/Redis -> env -> default),
DEFAULT ON; flipping it to false is the no-restart escape hatch back to
the legacy in-process launch (affects new calls only).

- The launch payload (room_url, token, lead/session ids) travels over
  stdin, never argv, so the Daily token is not visible in `ps`.
- The child inherits the environment, with POSTGRES_POOL_SIZE=1 /
  POSTGRES_MAX_OVERFLOW=2 overrides (init_db_pool eagerly opens
  min_size connections; a per-call child must not open the API pod's
  full pool). Override via BB_VOICE_BOT_DB_POOL_SIZE /
  BB_VOICE_BOT_DB_MAX_OVERFLOW.
- Child stdout/stderr are inherited, so its loguru output (same
  colored-dev / JSON-prod config, driven by the inherited ENVIRONMENT)
  lands in the same container log stream; log context (lead_id,
  call_sid, conversation_id) is set inside the bot exactly as before.
- A log-only reaper records the child's exit code; dead-bot recovery
  stays with the existing safety nets (/voice/end crash-net channel
  flip, 1h room expiry) — identical to a dead in-process task before.

No functionality changes: every bot<->API coordination path is already
process-agnostic (DB writes, the cross-process Redis session lock,
DB-backed approvals, the Daily room itself), and every resource the bot
needs is a lazy singleton (asyncpg pool, Redis) or env-driven. Applies
uniformly to widget DAILY_STREAM, demo, and dashboard daily bots.

Known deltas: bot join gains ~2-3s (child interpreter + imports; warm
pool is a follow-up if it matters), each call adds one process (own ONNX
copies) and 1-3 Postgres connections — size pods accordingly.

Verified: pyrefly 0 errors; 583 passed, 1 xfailed (9 new tests: stdin
payload round-trip incl. child-side parse, spawn args/env/stdin
contract, escape-hatch fallback to in-process); bot_runner smoke-tested
via `python -m` (invalid payload exits 2 with a clean error log).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JMS9AtnyXQXHADd1ca1TwK
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.

2 participants