Compare commits
13 Commits
v1.1.0
...
jh/aws-aut
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6da5c18b7 | ||
|
|
4b6881b81d | ||
|
|
bfdd19464f | ||
|
|
1a93ff52f1 | ||
|
|
6e2008a7a6 | ||
|
|
da8d3a2d80 | ||
|
|
6b608e7e22 | ||
|
|
924b9a9d8c | ||
|
|
9411c4b67e | ||
|
|
ac5eb97670 | ||
|
|
3034f8bb3b | ||
|
|
60c66eda48 | ||
|
|
ea3585146c |
28
README.md
28
README.md
@@ -89,20 +89,20 @@ Catch new features, interviews, and how-tos on our [Pipecat TV](https://www.yout
|
||||
|
||||
## 🧩 Available services
|
||||
|
||||
| Category | Services |
|
||||
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| Speech-to-Text | [AssemblyAI](https://docs.pipecat.ai/api-reference/server/services/stt/assemblyai), [AWS](https://docs.pipecat.ai/api-reference/server/services/stt/aws), [Azure](https://docs.pipecat.ai/api-reference/server/services/stt/azure), [Cartesia](https://docs.pipecat.ai/api-reference/server/services/stt/cartesia), [Deepgram](https://docs.pipecat.ai/api-reference/server/services/stt/deepgram), [ElevenLabs](https://docs.pipecat.ai/api-reference/server/services/stt/elevenlabs), [Fal Wizper](https://docs.pipecat.ai/api-reference/server/services/stt/fal), [Gladia](https://docs.pipecat.ai/api-reference/server/services/stt/gladia), [Google](https://docs.pipecat.ai/api-reference/server/services/stt/google), [Gradium](https://docs.pipecat.ai/api-reference/server/services/stt/gradium), [Groq (Whisper)](https://docs.pipecat.ai/api-reference/server/services/stt/groq), [Mistral](https://docs.pipecat.ai/api-reference/server/services/stt/mistral), [NVIDIA Riva](https://docs.pipecat.ai/api-reference/server/services/stt/riva), [OpenAI (Whisper)](https://docs.pipecat.ai/api-reference/server/services/stt/openai), [Sarvam](https://docs.pipecat.ai/api-reference/server/services/stt/sarvam), [Soniox](https://docs.pipecat.ai/api-reference/server/services/stt/soniox), [Speechmatics](https://docs.pipecat.ai/api-reference/server/services/stt/speechmatics), [Whisper](https://docs.pipecat.ai/api-reference/server/services/stt/whisper), [xAI](https://docs.pipecat.ai/api-reference/server/services/stt/xai) |
|
||||
| LLMs | [Anthropic](https://docs.pipecat.ai/api-reference/server/services/llm/anthropic), [AWS](https://docs.pipecat.ai/api-reference/server/services/llm/aws), [Azure](https://docs.pipecat.ai/api-reference/server/services/llm/azure), [Cerebras](https://docs.pipecat.ai/api-reference/server/services/llm/cerebras), [DeepSeek](https://docs.pipecat.ai/api-reference/server/services/llm/deepseek), [Fireworks AI](https://docs.pipecat.ai/api-reference/server/services/llm/fireworks), [Gemini](https://docs.pipecat.ai/api-reference/server/services/llm/gemini), [Grok](https://docs.pipecat.ai/api-reference/server/services/llm/grok), [Groq](https://docs.pipecat.ai/api-reference/server/services/llm/groq), [Mistral](https://docs.pipecat.ai/api-reference/server/services/llm/mistral), [Nebius](https://docs.pipecat.ai/api-reference/server/services/llm/nebius), [Novita](https://docs.pipecat.ai/api-reference/server/services/llm/novita), [NVIDIA NIM](https://docs.pipecat.ai/api-reference/server/services/llm/nvidia), [Ollama](https://docs.pipecat.ai/api-reference/server/services/llm/ollama), [OpenAI](https://docs.pipecat.ai/api-reference/server/services/llm/openai), [OpenAI Responses](https://docs.pipecat.ai/api-reference/server/services/llm/openai-responses), [OpenRouter](https://docs.pipecat.ai/api-reference/server/services/llm/openrouter), [Perplexity](https://docs.pipecat.ai/api-reference/server/services/llm/perplexity), [Qwen](https://docs.pipecat.ai/api-reference/server/services/llm/qwen), [SambaNova](https://docs.pipecat.ai/api-reference/server/services/llm/sambanova), [Sarvam](https://docs.pipecat.ai/api-reference/server/services/llm/sarvam), [Together AI](https://docs.pipecat.ai/api-reference/server/services/llm/together) |
|
||||
| Text-to-Speech | [Async](https://docs.pipecat.ai/api-reference/server/services/tts/asyncai), [AWS](https://docs.pipecat.ai/api-reference/server/services/tts/aws), [Azure](https://docs.pipecat.ai/api-reference/server/services/tts/azure), [Camb AI](https://docs.pipecat.ai/api-reference/server/services/tts/camb), [Cartesia](https://docs.pipecat.ai/api-reference/server/services/tts/cartesia), [Deepgram](https://docs.pipecat.ai/api-reference/server/services/tts/deepgram), [ElevenLabs](https://docs.pipecat.ai/api-reference/server/services/tts/elevenlabs), [Fish](https://docs.pipecat.ai/api-reference/server/services/tts/fish), [Google](https://docs.pipecat.ai/api-reference/server/services/tts/google), [Gradium](https://docs.pipecat.ai/api-reference/server/services/tts/gradium), [Groq](https://docs.pipecat.ai/api-reference/server/services/tts/groq), [Hume](https://docs.pipecat.ai/api-reference/server/services/tts/hume), [Inworld](https://docs.pipecat.ai/api-reference/server/services/tts/inworld), [Kokoro](https://docs.pipecat.ai/api-reference/server/services/tts/kokoro), [LMNT](https://docs.pipecat.ai/api-reference/server/services/tts/lmnt), [MiniMax](https://docs.pipecat.ai/api-reference/server/services/tts/minimax), [Mistral](https://docs.pipecat.ai/api-reference/server/services/tts/mistral), [Neuphonic](https://docs.pipecat.ai/api-reference/server/services/tts/neuphonic), [NVIDIA Riva](https://docs.pipecat.ai/api-reference/server/services/tts/riva), [OpenAI](https://docs.pipecat.ai/api-reference/server/services/tts/openai), [Piper](https://docs.pipecat.ai/api-reference/server/services/tts/piper), [Resemble](https://docs.pipecat.ai/api-reference/server/services/tts/resemble), [Rime](https://docs.pipecat.ai/api-reference/server/services/tts/rime), [Sarvam](https://docs.pipecat.ai/api-reference/server/services/tts/sarvam), [Smallest](https://docs.pipecat.ai/api-reference/server/services/tts/smallest), [Soniox](https://docs.pipecat.ai/api-reference/server/services/tts/soniox), [Speechmatics](https://docs.pipecat.ai/api-reference/server/services/tts/speechmatics), [xAI](https://docs.pipecat.ai/api-reference/server/services/tts/xai), [XTTS](https://docs.pipecat.ai/api-reference/server/services/tts/xtts) |
|
||||
| Speech-to-Speech | [AWS Nova Sonic](https://docs.pipecat.ai/api-reference/server/services/s2s/aws), [Gemini Multimodal Live](https://docs.pipecat.ai/api-reference/server/services/s2s/gemini), [Grok Voice Agent](https://docs.pipecat.ai/api-reference/server/services/s2s/grok), [OpenAI Realtime](https://docs.pipecat.ai/api-reference/server/services/s2s/openai), [Ultravox](https://docs.pipecat.ai/api-reference/server/services/s2s/ultravox), |
|
||||
| Transport | [Daily (WebRTC)](https://docs.pipecat.ai/api-reference/server/services/transport/daily), [FastAPI Websocket](https://docs.pipecat.ai/api-reference/server/services/transport/fastapi-websocket), [LiveKit (WebRTC)](https://docs.pipecat.ai/api-reference/server/services/transport/livekit), [SmallWebRTCTransport](https://docs.pipecat.ai/api-reference/server/services/transport/small-webrtc), [WebSocket Server](https://docs.pipecat.ai/api-reference/server/services/transport/websocket-server), [WhatsApp](https://docs.pipecat.ai/api-reference/server/services/transport/whatsapp), Local |
|
||||
| Serializers | [Exotel](https://docs.pipecat.ai/api-reference/server/services/serializers/exotel), [Genesys](https://docs.pipecat.ai/api-reference/server/services/serializers/genesys), [Plivo](https://docs.pipecat.ai/api-reference/server/services/serializers/plivo), [Twilio](https://docs.pipecat.ai/api-reference/server/services/serializers/twilio), [Telnyx](https://docs.pipecat.ai/api-reference/server/services/serializers/telnyx), [Vonage](https://docs.pipecat.ai/api-reference/server/services/serializers/vonage) |
|
||||
| Video | [HeyGen](https://docs.pipecat.ai/api-reference/server/services/video/heygen), [LemonSlice](https://docs.pipecat.ai/api-reference/server/services/transport/lemonslice), [Tavus](https://docs.pipecat.ai/api-reference/server/services/video/tavus), [Simli](https://docs.pipecat.ai/api-reference/server/services/video/simli) |
|
||||
| Memory | [mem0](https://docs.pipecat.ai/api-reference/server/services/memory/mem0) |
|
||||
| Vision & Image | [fal](https://docs.pipecat.ai/api-reference/server/services/image-generation/fal), [Google Imagen](https://docs.pipecat.ai/api-reference/server/services/image-generation/google-imagen), [Moondream](https://docs.pipecat.ai/api-reference/server/services/vision/moondream) |
|
||||
| Audio Processing | [Silero VAD](https://docs.pipecat.ai/api-reference/server/utilities/audio/silero-vad-analyzer), [Krisp Viva](https://docs.pipecat.ai/guides/features/krisp-viva), [Koala](https://docs.pipecat.ai/api-reference/server/utilities/audio/koala-filter), [ai-coustics](https://docs.pipecat.ai/api-reference/server/utilities/audio/aic-filter), [RNNoise](https://docs.pipecat.ai/api-reference/server/utilities/audio/rnnoise-filter) |
|
||||
| Analytics & Metrics | [OpenTelemetry](https://docs.pipecat.ai/api-reference/server/utilities/opentelemetry), [Sentry](https://docs.pipecat.ai/api-reference/server/services/analytics/sentry) |
|
||||
| Community | [Browse community integrations →](https://docs.pipecat.ai/api-reference/server/services/community-integrations) |
|
||||
| Category | Services |
|
||||
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Speech-to-Text | [AssemblyAI](https://docs.pipecat.ai/api-reference/server/services/stt/assemblyai), [AWS](https://docs.pipecat.ai/api-reference/server/services/stt/aws), [Azure](https://docs.pipecat.ai/api-reference/server/services/stt/azure), [Cartesia](https://docs.pipecat.ai/api-reference/server/services/stt/cartesia), [Deepgram](https://docs.pipecat.ai/api-reference/server/services/stt/deepgram), [ElevenLabs](https://docs.pipecat.ai/api-reference/server/services/stt/elevenlabs), [Fal Wizper](https://docs.pipecat.ai/api-reference/server/services/stt/fal), [Gladia](https://docs.pipecat.ai/api-reference/server/services/stt/gladia), [Google](https://docs.pipecat.ai/api-reference/server/services/stt/google), [Gradium](https://docs.pipecat.ai/api-reference/server/services/stt/gradium), [Groq (Whisper)](https://docs.pipecat.ai/api-reference/server/services/stt/groq), [Mistral](https://docs.pipecat.ai/api-reference/server/services/stt/mistral), [NVIDIA](https://docs.pipecat.ai/api-reference/server/services/stt/nvidia), [OpenAI (Whisper)](https://docs.pipecat.ai/api-reference/server/services/stt/openai), [Sarvam](https://docs.pipecat.ai/api-reference/server/services/stt/sarvam), [Soniox](https://docs.pipecat.ai/api-reference/server/services/stt/soniox), [Speechmatics](https://docs.pipecat.ai/api-reference/server/services/stt/speechmatics), [Whisper](https://docs.pipecat.ai/api-reference/server/services/stt/whisper), [xAI](https://docs.pipecat.ai/api-reference/server/services/stt/xai) |
|
||||
| LLMs | [Anthropic](https://docs.pipecat.ai/api-reference/server/services/llm/anthropic), [AWS](https://docs.pipecat.ai/api-reference/server/services/llm/aws), [Azure](https://docs.pipecat.ai/api-reference/server/services/llm/azure), [Cerebras](https://docs.pipecat.ai/api-reference/server/services/llm/cerebras), [DeepSeek](https://docs.pipecat.ai/api-reference/server/services/llm/deepseek), [Fireworks AI](https://docs.pipecat.ai/api-reference/server/services/llm/fireworks), [Gemini](https://docs.pipecat.ai/api-reference/server/services/llm/gemini), [Grok](https://docs.pipecat.ai/api-reference/server/services/llm/grok), [Groq](https://docs.pipecat.ai/api-reference/server/services/llm/groq), [Mistral](https://docs.pipecat.ai/api-reference/server/services/llm/mistral), [Nebius](https://docs.pipecat.ai/api-reference/server/services/llm/nebius), [Novita](https://docs.pipecat.ai/api-reference/server/services/llm/novita), [NVIDIA NIM](https://docs.pipecat.ai/api-reference/server/services/llm/nvidia), [Ollama](https://docs.pipecat.ai/api-reference/server/services/llm/ollama), [OpenAI](https://docs.pipecat.ai/api-reference/server/services/llm/openai), [OpenAI Responses](https://docs.pipecat.ai/api-reference/server/services/llm/openai-responses), [OpenRouter](https://docs.pipecat.ai/api-reference/server/services/llm/openrouter), [Perplexity](https://docs.pipecat.ai/api-reference/server/services/llm/perplexity), [Qwen](https://docs.pipecat.ai/api-reference/server/services/llm/qwen), [SambaNova](https://docs.pipecat.ai/api-reference/server/services/llm/sambanova), [Sarvam](https://docs.pipecat.ai/api-reference/server/services/llm/sarvam), [Together AI](https://docs.pipecat.ai/api-reference/server/services/llm/together) |
|
||||
| Text-to-Speech | [Async](https://docs.pipecat.ai/api-reference/server/services/tts/asyncai), [AWS](https://docs.pipecat.ai/api-reference/server/services/tts/aws), [Azure](https://docs.pipecat.ai/api-reference/server/services/tts/azure), [Camb AI](https://docs.pipecat.ai/api-reference/server/services/tts/camb), [Cartesia](https://docs.pipecat.ai/api-reference/server/services/tts/cartesia), [Deepgram](https://docs.pipecat.ai/api-reference/server/services/tts/deepgram), [ElevenLabs](https://docs.pipecat.ai/api-reference/server/services/tts/elevenlabs), [Fish](https://docs.pipecat.ai/api-reference/server/services/tts/fish), [Google](https://docs.pipecat.ai/api-reference/server/services/tts/google), [Gradium](https://docs.pipecat.ai/api-reference/server/services/tts/gradium), [Groq](https://docs.pipecat.ai/api-reference/server/services/tts/groq), [Hume](https://docs.pipecat.ai/api-reference/server/services/tts/hume), [Inworld](https://docs.pipecat.ai/api-reference/server/services/tts/inworld), [Kokoro](https://docs.pipecat.ai/api-reference/server/services/tts/kokoro), [LMNT](https://docs.pipecat.ai/api-reference/server/services/tts/lmnt), [MiniMax](https://docs.pipecat.ai/api-reference/server/services/tts/minimax), [Mistral](https://docs.pipecat.ai/api-reference/server/services/tts/mistral), [Neuphonic](https://docs.pipecat.ai/api-reference/server/services/tts/neuphonic), [NVIDIA](https://docs.pipecat.ai/api-reference/server/services/tts/nvidia), [OpenAI](https://docs.pipecat.ai/api-reference/server/services/tts/openai), [Piper](https://docs.pipecat.ai/api-reference/server/services/tts/piper), [Resemble](https://docs.pipecat.ai/api-reference/server/services/tts/resemble), [Rime](https://docs.pipecat.ai/api-reference/server/services/tts/rime), [Sarvam](https://docs.pipecat.ai/api-reference/server/services/tts/sarvam), [Smallest](https://docs.pipecat.ai/api-reference/server/services/tts/smallest), [Soniox](https://docs.pipecat.ai/api-reference/server/services/tts/soniox), [Speechmatics](https://docs.pipecat.ai/api-reference/server/services/tts/speechmatics), [xAI](https://docs.pipecat.ai/api-reference/server/services/tts/xai), [XTTS](https://docs.pipecat.ai/api-reference/server/services/tts/xtts) |
|
||||
| Speech-to-Speech | [AWS Nova Sonic](https://docs.pipecat.ai/api-reference/server/services/s2s/aws), [Gemini Multimodal Live](https://docs.pipecat.ai/api-reference/server/services/s2s/gemini), [Grok Voice Agent](https://docs.pipecat.ai/api-reference/server/services/s2s/grok), [OpenAI Realtime](https://docs.pipecat.ai/api-reference/server/services/s2s/openai), [Ultravox](https://docs.pipecat.ai/api-reference/server/services/s2s/ultravox), |
|
||||
| Transport | [Daily (WebRTC)](https://docs.pipecat.ai/api-reference/server/services/transport/daily), [FastAPI Websocket](https://docs.pipecat.ai/api-reference/server/services/transport/fastapi-websocket), [LiveKit (WebRTC)](https://docs.pipecat.ai/api-reference/server/services/transport/livekit), [SmallWebRTCTransport](https://docs.pipecat.ai/api-reference/server/services/transport/small-webrtc), [WebSocket Server](https://docs.pipecat.ai/api-reference/server/services/transport/websocket-server), [WhatsApp](https://docs.pipecat.ai/api-reference/server/services/transport/whatsapp), Local |
|
||||
| Serializers | [Exotel](https://docs.pipecat.ai/api-reference/server/services/serializers/exotel), [Genesys](https://docs.pipecat.ai/api-reference/server/services/serializers/genesys), [Plivo](https://docs.pipecat.ai/api-reference/server/services/serializers/plivo), [Twilio](https://docs.pipecat.ai/api-reference/server/services/serializers/twilio), [Telnyx](https://docs.pipecat.ai/api-reference/server/services/serializers/telnyx), [Vonage](https://docs.pipecat.ai/api-reference/server/services/serializers/vonage) |
|
||||
| Video | [HeyGen](https://docs.pipecat.ai/api-reference/server/services/video/heygen), [LemonSlice](https://docs.pipecat.ai/api-reference/server/services/transport/lemonslice), [Tavus](https://docs.pipecat.ai/api-reference/server/services/video/tavus), [Simli](https://docs.pipecat.ai/api-reference/server/services/video/simli) |
|
||||
| Memory | [mem0](https://docs.pipecat.ai/api-reference/server/services/memory/mem0) |
|
||||
| Vision & Image | [fal](https://docs.pipecat.ai/api-reference/server/services/image-generation/fal), [Google Imagen](https://docs.pipecat.ai/api-reference/server/services/image-generation/google-imagen), [Moondream](https://docs.pipecat.ai/api-reference/server/services/vision/moondream) |
|
||||
| Audio Processing | [Silero VAD](https://docs.pipecat.ai/api-reference/server/utilities/audio/silero-vad-analyzer), [Krisp Viva](https://docs.pipecat.ai/guides/features/krisp-viva), [Koala](https://docs.pipecat.ai/api-reference/server/utilities/audio/koala-filter), [ai-coustics](https://docs.pipecat.ai/api-reference/server/utilities/audio/aic-filter), [RNNoise](https://docs.pipecat.ai/api-reference/server/utilities/audio/rnnoise-filter) |
|
||||
| Analytics & Metrics | [OpenTelemetry](https://docs.pipecat.ai/api-reference/server/utilities/opentelemetry), [Sentry](https://docs.pipecat.ai/api-reference/server/services/analytics/sentry) |
|
||||
| Community | [Browse community integrations →](https://docs.pipecat.ai/api-reference/server/services/community-integrations) |
|
||||
|
||||
📚 [View full services documentation →](https://docs.pipecat.ai/api-reference/server/services/supported-services)
|
||||
|
||||
|
||||
1
changelog/4385.added.md
Normal file
1
changelog/4385.added.md
Normal file
@@ -0,0 +1 @@
|
||||
- Added a `session_id` field to `RunnerArguments` so bots can log or trace a per-session identifier in local development the same way they can in Pipecat Cloud. The development runner now mints a UUID at every construction site, and paths that already returned a `sessionId` to the caller (Daily `/start`, dial-in webhook) share that same UUID with the runner args instead of generating two. The SmallWebRTC `/api/offer` endpoint also accepts an optional `session_id` query parameter so the `/sessions/{session_id}/...` proxy can thread it through.
|
||||
1
changelog/4386.changed.md
Normal file
1
changelog/4386.changed.md
Normal file
@@ -0,0 +1 @@
|
||||
- Updated the default `SonioxTTSService` model from `tts-rt-v1-preview` to the generally available `tts-rt-v1`.
|
||||
9
changelog/4389.fixed.md
Normal file
9
changelog/4389.fixed.md
Normal file
@@ -0,0 +1,9 @@
|
||||
- Fixed AWS services failing silently on missing or invalid credentials.
|
||||
`AWSNovaSonicLLMService`, `AWSBedrockLLMService`, `AWSPollyTTSService`,
|
||||
and `AWSTranscribeSTTService` now push a fatal `ErrorFrame` with a
|
||||
"check AWS credentials and region" hint on auth-class failures, so the
|
||||
pipeline cancels promptly instead of continuing to run with no output.
|
||||
- Fixed `AWSNovaSonicLLMService._disconnect` raising `InvalidStateError`
|
||||
from `awscrt/aio/http.py` when cleanup ran on a stream from a failed
|
||||
`invoke_model_with_bidirectional_stream` call. The error was masking
|
||||
the real connect-time auth failure in the logs.
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
{% for text, values in sections[section][category].items() %}
|
||||
{{ text }}
|
||||
(PR {{ values|join(', ') }})
|
||||
(PR {{ values|join(', ') }})
|
||||
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
96
scripts/release-changelog.py
Executable file
96
scripts/release-changelog.py
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate release notes from CHANGELOG.md for use in GitHub Releases (or anywhere).
|
||||
|
||||
Usage::
|
||||
|
||||
python scripts/release-changelog.py VERSION
|
||||
python scripts/release-changelog.py 1.1.0
|
||||
python scripts/release-changelog.py --file path/to/CHANGELOG.md 1.1.0
|
||||
|
||||
Extracts the requested ``## [VERSION]`` section (heading and ``### …``
|
||||
subheadings included) and prints it to stdout. The only transformation
|
||||
applied is collapsing each entry paragraph onto a single line, so it is
|
||||
suitable for pasting into release notes that don't need 80-column wrapping.
|
||||
``(PR [...])`` references stay on their own two-space-indented continuation
|
||||
line. The input file is never modified.
|
||||
|
||||
Every paragraph is unfilled. Indentation is preserved — each logical line
|
||||
(bullets, sub-bullets, and the ``(PR [...])`` continuation) keeps its
|
||||
leading whitespace; only the wrapped continuation lines that follow them
|
||||
get joined back. Code-block paragraphs (triple-backtick fences, or deeply
|
||||
indented blocks with no list markers around) are passed through untouched.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
DEFAULT_CHANGELOG = Path(__file__).resolve().parent.parent / "CHANGELOG.md"
|
||||
|
||||
PARAGRAPH_SPLIT_RE = re.compile(r"(\n[ \t]*\n+)")
|
||||
CONTINUATION_RE = re.compile(r"\n(?![ \t]*[-*+] )[ \t]+")
|
||||
PR_RE = re.compile(r" \(PR \[")
|
||||
CODE_FENCE_RE = re.compile(r"^\s*```")
|
||||
DEEP_INDENT_RE = re.compile(r"^ {4,}")
|
||||
LIST_MARKER_RE = re.compile(r"^[ \t]*[-*+] ")
|
||||
SECTION_HEADING_RE = re.compile(r"^## \[", re.MULTILINE)
|
||||
|
||||
|
||||
def is_code_block_paragraph(paragraph: str) -> bool:
|
||||
lines = paragraph.splitlines()
|
||||
if any(CODE_FENCE_RE.match(line) for line in lines):
|
||||
return True
|
||||
# In a list paragraph, 4-space indent is a sub-bullet continuation, not
|
||||
# code. Only treat deep-indented lines as code when no bullets are around
|
||||
# to claim them.
|
||||
if any(LIST_MARKER_RE.match(line) for line in lines):
|
||||
return False
|
||||
return any(DEEP_INDENT_RE.match(line) for line in lines)
|
||||
|
||||
|
||||
def unfill_entry(paragraph: str) -> str:
|
||||
joined = CONTINUATION_RE.sub(" ", paragraph)
|
||||
return PR_RE.sub("\n (PR [", joined, count=1)
|
||||
|
||||
|
||||
def process(text: str) -> str:
|
||||
parts = PARAGRAPH_SPLIT_RE.split(text)
|
||||
for i in range(0, len(parts), 2):
|
||||
para = parts[i]
|
||||
if para and not is_code_block_paragraph(para):
|
||||
parts[i] = unfill_entry(para)
|
||||
return "".join(parts)
|
||||
|
||||
|
||||
def extract_section(text: str, version: str) -> str:
|
||||
head_re = re.compile(rf"^## \[{re.escape(version)}\]", re.MULTILINE)
|
||||
m = head_re.search(text)
|
||||
if not m:
|
||||
sys.exit(f"error: version {version!r} not found")
|
||||
nxt = SECTION_HEADING_RE.search(text, m.end())
|
||||
end = nxt.start() if nxt else len(text)
|
||||
return text[m.start() : end]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
summary = (__doc__ or "").splitlines()[0]
|
||||
parser = argparse.ArgumentParser(description=summary)
|
||||
parser.add_argument("version", help="Version to extract (e.g. 1.1.0).")
|
||||
parser.add_argument(
|
||||
"--file",
|
||||
type=Path,
|
||||
default=DEFAULT_CHANGELOG,
|
||||
help=f"Path to the changelog (default: {DEFAULT_CHANGELOG}).",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
text = args.file.read_text()
|
||||
section = extract_section(text, args.version)
|
||||
sys.stdout.write(process(section))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -180,7 +180,7 @@ async def _run_telephony_bot(websocket: WebSocket, args: argparse.Namespace):
|
||||
bot_module = _get_bot_module()
|
||||
|
||||
# Just pass the WebSocket - let the bot handle parsing
|
||||
runner_args = WebSocketRunnerArguments(websocket=websocket)
|
||||
runner_args = WebSocketRunnerArguments(websocket=websocket, session_id=str(uuid.uuid4()))
|
||||
runner_args.cli_args = args
|
||||
|
||||
await bot_module.bot(runner_args)
|
||||
@@ -267,15 +267,25 @@ def _setup_webrtc_routes(app: FastAPI, args: argparse.Namespace):
|
||||
)
|
||||
|
||||
@app.post("/api/offer")
|
||||
async def offer(request: SmallWebRTCRequest, background_tasks: BackgroundTasks):
|
||||
async def offer(
|
||||
request: SmallWebRTCRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
session_id: str | None = None,
|
||||
):
|
||||
"""Handle WebRTC offer requests via SmallWebRTCRequestHandler."""
|
||||
# When called via the /sessions/{session_id}/api/offer proxy the
|
||||
# session_id is threaded through; for direct /api/offer calls we mint
|
||||
# one so bots see a stable identifier in either path.
|
||||
resolved_session_id = session_id or str(uuid.uuid4())
|
||||
|
||||
# Prepare runner arguments with the callback to run your bot
|
||||
async def webrtc_connection_callback(connection: SmallWebRTCConnection):
|
||||
bot_module = _get_bot_module()
|
||||
|
||||
runner_args = SmallWebRTCRunnerArguments(
|
||||
webrtc_connection=connection, body=request.request_data
|
||||
webrtc_connection=connection,
|
||||
body=request.request_data,
|
||||
session_id=resolved_session_id,
|
||||
)
|
||||
runner_args.cli_args = args
|
||||
background_tasks.add_task(bot_module.bot, runner_args)
|
||||
@@ -343,7 +353,7 @@ def _setup_webrtc_routes(app: FastAPI, args: argparse.Namespace):
|
||||
or request_data.get("requestData")
|
||||
or active_session,
|
||||
)
|
||||
return await offer(webrtc_request, background_tasks)
|
||||
return await offer(webrtc_request, background_tasks, session_id=session_id)
|
||||
elif request.method == HTTPMethod.PATCH.value:
|
||||
patch_request = SmallWebRTCPatchRequest(
|
||||
pc_id=request_data["pc_id"],
|
||||
@@ -490,7 +500,9 @@ def _setup_whatsapp_routes(app: FastAPI, args: argparse.Namespace):
|
||||
connection: The established WebRTC connection
|
||||
"""
|
||||
bot_module = _get_bot_module()
|
||||
runner_args = SmallWebRTCRunnerArguments(webrtc_connection=connection)
|
||||
runner_args = SmallWebRTCRunnerArguments(
|
||||
webrtc_connection=connection, session_id=str(uuid.uuid4())
|
||||
)
|
||||
runner_args.cli_args = args
|
||||
background_tasks.add_task(bot_module.bot, runner_args)
|
||||
|
||||
@@ -554,7 +566,9 @@ def _setup_daily_routes(app: FastAPI, args: argparse.Namespace):
|
||||
|
||||
# Start the bot in the background with empty body for GET requests
|
||||
bot_module = _get_bot_module()
|
||||
runner_args = DailyRunnerArguments(room_url=room_url, token=token)
|
||||
runner_args = DailyRunnerArguments(
|
||||
room_url=room_url, token=token, session_id=str(uuid.uuid4())
|
||||
)
|
||||
runner_args.cli_args = args
|
||||
asyncio.create_task(bot_module.bot(runner_args))
|
||||
return RedirectResponse(room_url)
|
||||
@@ -590,6 +604,7 @@ def _setup_daily_routes(app: FastAPI, args: argparse.Namespace):
|
||||
|
||||
existing_room_url = os.getenv("DAILY_ROOM_URL")
|
||||
|
||||
session_id = str(uuid.uuid4())
|
||||
result = None
|
||||
|
||||
# Configure room if:
|
||||
@@ -638,14 +653,16 @@ def _setup_daily_routes(app: FastAPI, args: argparse.Namespace):
|
||||
room_properties=room_properties,
|
||||
token_properties=token_properties,
|
||||
)
|
||||
runner_args = DailyRunnerArguments(room_url=room_url, token=token, body=body)
|
||||
runner_args = DailyRunnerArguments(
|
||||
room_url=room_url, token=token, body=body, session_id=session_id
|
||||
)
|
||||
result = {
|
||||
"dailyRoom": room_url,
|
||||
"dailyToken": token,
|
||||
"sessionId": str(uuid.uuid4()),
|
||||
"sessionId": session_id,
|
||||
}
|
||||
else:
|
||||
runner_args = RunnerArguments(body=body)
|
||||
runner_args = RunnerArguments(body=body, session_id=session_id)
|
||||
|
||||
# Update CLI args.
|
||||
runner_args.cli_args = args
|
||||
@@ -749,20 +766,21 @@ def _setup_daily_routes(app: FastAPI, args: argparse.Namespace):
|
||||
daily_api_url=daily_api_url,
|
||||
)
|
||||
|
||||
# Generate session ID for both the runner args and the response
|
||||
session_id = str(uuid.uuid4())
|
||||
|
||||
# Start bot with dial-in context
|
||||
bot_module = _get_bot_module()
|
||||
runner_args = DailyRunnerArguments(
|
||||
room_url=room_config.room_url,
|
||||
token=room_config.token,
|
||||
body=request_body.model_dump(),
|
||||
session_id=session_id,
|
||||
)
|
||||
runner_args.cli_args = args
|
||||
|
||||
asyncio.create_task(bot_module.bot(runner_args))
|
||||
|
||||
# Generate session ID
|
||||
session_id = str(uuid.uuid4())
|
||||
|
||||
# Return response matching Pipecat Cloud format
|
||||
return {
|
||||
"dailyRoom": room_config.room_url,
|
||||
@@ -838,7 +856,9 @@ async def _run_daily_direct(args: argparse.Namespace):
|
||||
room_url, token = await configure(session, room_exp_duration=PIPECAT_ROOM_EXP_HOURS)
|
||||
|
||||
# Direct connections have no request body, so use empty dict
|
||||
runner_args = DailyRunnerArguments(room_url=room_url, token=token)
|
||||
runner_args = DailyRunnerArguments(
|
||||
room_url=room_url, token=token, session_id=str(uuid.uuid4())
|
||||
)
|
||||
runner_args.handle_sigint = True
|
||||
runner_args.cli_args = args
|
||||
|
||||
|
||||
@@ -58,13 +58,25 @@ class DailyDialinRequest(BaseModel):
|
||||
|
||||
@dataclass
|
||||
class RunnerArguments:
|
||||
"""Base class for runner session arguments."""
|
||||
"""Base class for runner session arguments.
|
||||
|
||||
Parameters:
|
||||
handle_sigint: Whether the bot should install a SIGINT handler.
|
||||
handle_sigterm: Whether the bot should install a SIGTERM handler.
|
||||
pipeline_idle_timeout_secs: Seconds the pipeline may stay idle before
|
||||
shutting down.
|
||||
body: Optional request body data passed from the runner entry point.
|
||||
session_id: Identifier for this bot session.
|
||||
cli_args: Parsed CLI arguments from the runner, when launched via the
|
||||
development runner.
|
||||
"""
|
||||
|
||||
# Use kw_only so subclasses don't need to worry about ordering.
|
||||
handle_sigint: bool = field(init=False, kw_only=True)
|
||||
handle_sigterm: bool = field(init=False, kw_only=True)
|
||||
pipeline_idle_timeout_secs: int = field(init=False, kw_only=True)
|
||||
body: Any | None = field(default_factory=dict, kw_only=True)
|
||||
session_id: str | None = field(default=None, kw_only=True)
|
||||
cli_args: argparse.Namespace | None = field(default=None, init=False, kw_only=True)
|
||||
|
||||
def __post_init__(self):
|
||||
|
||||
@@ -43,7 +43,7 @@ from pipecat.utils.tracing.service_decorators import traced_llm
|
||||
try:
|
||||
import aioboto3
|
||||
from botocore.config import Config
|
||||
from botocore.exceptions import ReadTimeoutError
|
||||
from botocore.exceptions import ClientError, ReadTimeoutError
|
||||
except ModuleNotFoundError as e:
|
||||
logger.error(f"Exception: {e}")
|
||||
logger.error(
|
||||
@@ -52,6 +52,23 @@ except ModuleNotFoundError as e:
|
||||
raise Exception(f"Missing module: {e}")
|
||||
|
||||
|
||||
# AWS error codes that indicate the service won't work until creds/region are
|
||||
# fixed. We treat these as fatal so the pipeline stops instead of silently
|
||||
# degrading.
|
||||
_AWS_AUTH_ERROR_CODES = frozenset(
|
||||
{
|
||||
"UnrecognizedClientException",
|
||||
"InvalidSignatureException",
|
||||
"AccessDeniedException",
|
||||
"ExpiredTokenException",
|
||||
"InvalidAccessKeyId",
|
||||
"SignatureDoesNotMatch",
|
||||
"MissingAuthenticationTokenException",
|
||||
"AuthFailure",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class AWSBedrockLLMSettings(LLMSettings):
|
||||
"""Settings for AWSBedrockLLMService.
|
||||
@@ -555,6 +572,20 @@ class AWSBedrockLLMService(LLMService):
|
||||
raise
|
||||
except (TimeoutError, ReadTimeoutError):
|
||||
await self._call_event_handler("on_completion_timeout")
|
||||
except ClientError as e:
|
||||
error_code = e.response.get("Error", {}).get("Code", "")
|
||||
if error_code in _AWS_AUTH_ERROR_CODES:
|
||||
await self.push_error(
|
||||
error_msg=(
|
||||
"AWS Bedrock authentication failed. "
|
||||
"Check AWS credentials and region. "
|
||||
f"Underlying error: {e}"
|
||||
),
|
||||
exception=e,
|
||||
fatal=True,
|
||||
)
|
||||
else:
|
||||
await self.push_error(error_msg=f"AWS Bedrock client error: {e}", exception=e)
|
||||
except Exception as e:
|
||||
await self.push_error(error_msg=f"Unknown error occurred: {e}", exception=e)
|
||||
finally:
|
||||
|
||||
@@ -602,7 +602,19 @@ class AWSNovaSonicLLMService(LLMService):
|
||||
self._ready_to_send_context = True
|
||||
await self._finish_connecting_if_context_available()
|
||||
except Exception as e:
|
||||
await self.push_error(error_msg=f"Initialization error: {e}", exception=e)
|
||||
# Connect-time failures (most commonly bad/missing AWS credentials or
|
||||
# an unsupported region) leave the bidirectional stream in a partial
|
||||
# state and produce no audio output. Treat them as fatal so the
|
||||
# pipeline cancels with a clear ERROR rather than continuing silently.
|
||||
await self.push_error(
|
||||
error_msg=(
|
||||
"AWS Nova Sonic failed to start. "
|
||||
"Check AWS credentials and region. "
|
||||
f"Underlying error: {e}"
|
||||
),
|
||||
exception=e,
|
||||
fatal=True,
|
||||
)
|
||||
await self._disconnect()
|
||||
|
||||
async def _process_completed_function_calls(self, send_new_results: bool):
|
||||
@@ -703,17 +715,28 @@ class AWSNovaSonicLLMService(LLMService):
|
||||
# NOTE: see explanation of HACK, below
|
||||
self._disconnecting = True
|
||||
|
||||
# Clean up client
|
||||
# Clean up client. If connect failed (e.g. bad credentials), the
|
||||
# session may not have started, so end events can fail. Don't let
|
||||
# that mask the real error or block cleanup.
|
||||
if self._client:
|
||||
await self._send_session_end_events()
|
||||
try:
|
||||
await self._send_session_end_events()
|
||||
except Exception as e:
|
||||
logger.debug(f"Ignoring error while sending session-end events: {e}")
|
||||
self._client = None
|
||||
|
||||
# Clean up context
|
||||
self._context = None
|
||||
|
||||
# Clean up stream
|
||||
# Clean up stream. A stream from a failed
|
||||
# invoke_model_with_bidirectional_stream call has an already-
|
||||
# cancelled awscrt future; closing it raises InvalidStateError that
|
||||
# otherwise drowns out the real connect error in the logs.
|
||||
if self._stream:
|
||||
await self._stream.close()
|
||||
try:
|
||||
await self._stream.close()
|
||||
except Exception as e:
|
||||
logger.debug(f"Ignoring error while closing partial stream: {e}")
|
||||
self._stream = None
|
||||
|
||||
# NOTE: see explanation of HACK, below
|
||||
|
||||
@@ -323,8 +323,18 @@ class AWSTranscribeSTTService(WebsocketSTTService):
|
||||
await self._call_event_handler("on_connected")
|
||||
logger.info(f"{self} Successfully connected to AWS Transcribe")
|
||||
except Exception as e:
|
||||
# Connect-time failures (most commonly bad/missing AWS credentials,
|
||||
# an unsupported region, or a 403 from the presigned URL) won't
|
||||
# recover on retry. Treat them as fatal so the pipeline cancels
|
||||
# with a clear ERROR rather than silently producing no transcripts.
|
||||
await self.push_error(
|
||||
error_msg=f"Unable to connect to AWS Transcribe: {e}", exception=e
|
||||
error_msg=(
|
||||
"Unable to connect to AWS Transcribe. "
|
||||
"Check AWS credentials and region. "
|
||||
f"Underlying error: {e}"
|
||||
),
|
||||
exception=e,
|
||||
fatal=True,
|
||||
)
|
||||
raise
|
||||
|
||||
|
||||
@@ -37,6 +37,23 @@ except ModuleNotFoundError as e:
|
||||
raise Exception(f"Missing module: {e}")
|
||||
|
||||
|
||||
# AWS error codes that indicate the service won't work until creds/region are
|
||||
# fixed. We treat these as fatal so the pipeline stops instead of silently
|
||||
# degrading.
|
||||
_AWS_AUTH_ERROR_CODES = frozenset(
|
||||
{
|
||||
"UnrecognizedClientException",
|
||||
"InvalidSignatureException",
|
||||
"AccessDeniedException",
|
||||
"ExpiredTokenException",
|
||||
"InvalidAccessKeyId",
|
||||
"SignatureDoesNotMatch",
|
||||
"MissingAuthenticationTokenException",
|
||||
"AuthFailure",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def language_to_aws_language(language: Language) -> str | None:
|
||||
"""Convert a Language enum to AWS Polly language code.
|
||||
|
||||
@@ -366,6 +383,21 @@ class AWSPollyTTSService(TTSService):
|
||||
frame = TTSAudioRawFrame(chunk, self.sample_rate, 1, context_id=context_id)
|
||||
yield frame
|
||||
|
||||
except (BotoCoreError, ClientError) as error:
|
||||
error_message = f"AWS Polly TTS error: {str(error)}"
|
||||
yield ErrorFrame(error=error_message)
|
||||
except ClientError as error:
|
||||
error_code = error.response.get("Error", {}).get("Code", "")
|
||||
if error_code in _AWS_AUTH_ERROR_CODES:
|
||||
# Bad/missing credentials won't fix themselves between calls.
|
||||
# Stop the pipeline so the failure surfaces clearly.
|
||||
await self.push_error(
|
||||
error_msg=(
|
||||
"AWS Polly authentication failed. "
|
||||
"Check AWS credentials and region. "
|
||||
f"Underlying error: {error}"
|
||||
),
|
||||
exception=error,
|
||||
fatal=True,
|
||||
)
|
||||
else:
|
||||
yield ErrorFrame(error=f"AWS Polly TTS error: {error}")
|
||||
except BotoCoreError as error:
|
||||
yield ErrorFrame(error=f"AWS Polly TTS error: {error}")
|
||||
|
||||
@@ -184,7 +184,7 @@ class SonioxTTSService(WebsocketTTSService):
|
||||
"""
|
||||
# Initialize default_settings
|
||||
default_settings = self.Settings(
|
||||
model="tts-rt-v1-preview",
|
||||
model="tts-rt-v1",
|
||||
voice="Adrian",
|
||||
language=Language.EN,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user