diff --git a/wavefront/client/src/config/voice-providers.ts b/wavefront/client/src/config/voice-providers.ts index 053f4068..252f0e87 100644 --- a/wavefront/client/src/config/voice-providers.ts +++ b/wavefront/client/src/config/voice-providers.ts @@ -304,7 +304,7 @@ export const VOICE_PROVIDERS_CONFIG: VoiceProvidersConfig = { model: { type: 'string', default: 'saarika:v2.5', - options: ['saarika:v2.5', 'saaras:v2'], + options: ['saarika:v2.5', 'saaras:v2.5', 'saaras:v3'], description: 'Sarvam STT model', }, language: { diff --git a/wavefront/server/apps/call_processing/call_processing/controllers/webhook_controller.py b/wavefront/server/apps/call_processing/call_processing/controllers/webhook_controller.py index 718c90c0..791afcd3 100644 --- a/wavefront/server/apps/call_processing/call_processing/controllers/webhook_controller.py +++ b/wavefront/server/apps/call_processing/call_processing/controllers/webhook_controller.py @@ -76,19 +76,6 @@ async def inbound_webhook( agent_id = agent['id'] logger.info(f'Agent found for inbound number {To}: {agent_id} ({agent["name"]})') - # Generate welcome message audio URL - welcome_message_audio_url = '' - if agent.get('welcome_message'): - try: - # Note: This assumes voice_agent_cache_service has this method - # We'll implement it in the next step - welcome_message_audio_url = ( - await voice_agent_cache_service.get_welcome_message_audio_url(agent_id) - ) - except Exception as e: - logger.error(f'Failed to get welcome message URL: {e}') - # Continue without welcome message - # Build WebSocket URL base_url = os.getenv('CALL_PROCESSING_BASE_URL', 'http://localhost:8003') @@ -107,14 +94,6 @@ async def inbound_webhook( # Generate TwiML response response = VoiceResponse() - # Play welcome message audio if URL is provided - if welcome_message_audio_url: - response.play(welcome_message_audio_url) - else: - logger.warning( - 'No welcome message audio URL provided, skipping welcome message' - ) - connect = Connect() stream = Stream(url=websocket_url) @@ -219,7 +198,6 @@ async def twiml_endpoint( From: str = Form(...), To: str = Form(...), voice_agent_id: str = Query(...), - welcome_message_audio_url: str = Query(default=''), ): """ Twilio TwiML endpoint @@ -229,10 +207,8 @@ async def twiml_endpoint( Query params: voice_agent_id: UUID of the voice agent configuration - welcome_message_audio_url: URL of the welcome message audio file """ logger.info(f'TwiML requested for voice_agent_id: {voice_agent_id}') - logger.info(f'Welcome message audio URL: {welcome_message_audio_url}') # Build WebSocket URL base_url = os.getenv('CALL_PROCESSING_BASE_URL', 'http://localhost:8003') @@ -252,14 +228,6 @@ async def twiml_endpoint( # Generate TwiML response response = VoiceResponse() - # Play welcome message audio if URL is provided - if welcome_message_audio_url: - response.play(welcome_message_audio_url) - else: - logger.warning( - 'No welcome message audio URL provided, skipping welcome message' - ) - connect = Connect() stream = Stream(url=websocket_url) diff --git a/wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py b/wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py index d63a0c2c..2e23f1b1 100644 --- a/wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py +++ b/wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py @@ -14,7 +14,7 @@ from pipecat.adapters.schemas.tools_schema import ToolsSchema from pipecat.adapters.schemas.function_schema import FunctionSchema from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3 -from pipecat.frames.frames import Frame +from pipecat.frames.frames import Frame, TTSSpeakFrame from pipecat.pipeline.parallel_pipeline import ParallelPipeline from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.runner import PipelineRunner @@ -36,7 +36,7 @@ from pipecat.transports.base_transport import BaseTransport from pipecat.turns.user_mute import ( FunctionCallUserMuteStrategy, - # MuteUntilFirstBotCompleteUserMuteStrategy, + MuteUntilFirstBotCompleteUserMuteStrategy, ) from pipecat.turns.user_turn_strategies import UserTurnStrategies from pipecat.turns.user_start import ( @@ -320,7 +320,8 @@ async def run_conversation( { 'role': 'system', 'content': system_content, - } + }, + {'role': 'assistant', 'content': agent_config['welcome_message']}, ] # Load and register tools for this agent @@ -465,7 +466,7 @@ async def run_conversation( ], # List of stop strategies ), user_mute_strategies=[ - # MuteUntilFirstBotCompleteUserMuteStrategy(), # Not needed since first message is pre-recorded audio + MuteUntilFirstBotCompleteUserMuteStrategy(), FunctionCallUserMuteStrategy(), ], ), @@ -510,7 +511,7 @@ async def run_conversation( @transport.event_handler('on_client_connected') async def on_client_connected(transport, client): logger.info(f"Client connected for agent: {agent_config['name']}") - # Bot waits for user to speak first (can be changed to greet first) + await task.queue_frame(TTSSpeakFrame(agent_config['welcome_message'])) @transport.event_handler('on_client_disconnected') async def on_client_disconnected(transport, client): @@ -519,6 +520,14 @@ async def on_client_disconnected(transport, client): # Run pipeline runner = PipelineRunner(handle_sigint=False) - await runner.run(task) - - logger.info(f"Conversation ended for agent: {agent_config['name']}") + try: + await runner.run(task) + except Exception as e: + logger.error( + f"Pipeline error for agent {agent_config['name']}: {e}", + exc_info=True, + ) + raise + finally: + await task.cancel() + logger.info(f"Conversation ended for agent: {agent_config['name']}") diff --git a/wavefront/server/apps/call_processing/pyproject.toml b/wavefront/server/apps/call_processing/pyproject.toml index 49a38829..905ddaf2 100644 --- a/wavefront/server/apps/call_processing/pyproject.toml +++ b/wavefront/server/apps/call_processing/pyproject.toml @@ -21,7 +21,7 @@ dependencies = [ "redis>=5.0.0", "tenacity>=8.0.0", # Pipecat and voice processing - "pipecat-ai[websocket,cartesia,google,silero,deepgram,groq,runner,azure,local-smart-turn-v3,sarvam]==0.0.100", + "pipecat-ai[websocket,cartesia,google,silero,deepgram,groq,runner,azure,local-smart-turn-v3,sarvam]==0.0.102", # Twilio "twilio>=8.0.0", ] diff --git a/wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/voice_agent_controller.py b/wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/voice_agent_controller.py index 98ef2cfc..c108f3a6 100644 --- a/wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/voice_agent_controller.py +++ b/wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/voice_agent_controller.py @@ -390,17 +390,6 @@ async def initiate_call( provider = telephony_config.get('provider') credentials = telephony_config.get('credentials', {}) - # Generate presigned URL for welcome message audio - welcome_message_audio_url = '' - if agent_dict.get('welcome_message'): - try: - welcome_message_audio_url = ( - await voice_agent_service.get_welcome_message_audio_url(agent_id) - ) - except Exception as e: - logger.error(f'Failed to generate welcome message audio URL: {str(e)}') - # Continue with empty URL - call will proceed without welcome message - # Route to appropriate provider service if provider == TelephonyProvider.TWILIO.value: account_sid = credentials.get('account_sid') @@ -418,7 +407,6 @@ async def initiate_call( to_number=payload.to_number, from_number=from_number, voice_agent_id=str(agent_id), - welcome_message_audio_url=welcome_message_audio_url, account_sid=account_sid, auth_token=auth_token, ) @@ -441,7 +429,6 @@ async def initiate_call( to_number=payload.to_number, from_number=from_number, voice_agent_id=str(agent_id), - welcome_message_audio_url=welcome_message_audio_url, api_key=api_key, api_token=api_token, account_sid=account_sid, diff --git a/wavefront/server/modules/voice_agents_module/voice_agents_module/services/exotel_service.py b/wavefront/server/modules/voice_agents_module/voice_agents_module/services/exotel_service.py index bd1c61b9..dfab9b94 100644 --- a/wavefront/server/modules/voice_agents_module/voice_agents_module/services/exotel_service.py +++ b/wavefront/server/modules/voice_agents_module/voice_agents_module/services/exotel_service.py @@ -19,7 +19,6 @@ async def initiate_call( to_number: str, from_number: str, voice_agent_id: str, - welcome_message_audio_url: str, api_key: str, api_token: str, account_sid: str, @@ -32,7 +31,6 @@ async def initiate_call( to_number: Destination phone number (E.164 format) from_number: Exotel virtual number (ExoPhone) voice_agent_id: ID of the voice agent - welcome_message_audio_url: URL of the welcome message audio file api_key: Exotel API key api_token: Exotel API token account_sid: Exotel account SID diff --git a/wavefront/server/modules/voice_agents_module/voice_agents_module/services/twilio_service.py b/wavefront/server/modules/voice_agents_module/voice_agents_module/services/twilio_service.py index 4ea32657..dd5d3c7e 100644 --- a/wavefront/server/modules/voice_agents_module/voice_agents_module/services/twilio_service.py +++ b/wavefront/server/modules/voice_agents_module/voice_agents_module/services/twilio_service.py @@ -1,6 +1,5 @@ from twilio.rest import Client as TwilioClient from common_module.log.logger import logger -from urllib.parse import quote class TwilioService: @@ -17,7 +16,6 @@ def initiate_call( to_number: str, from_number: str, voice_agent_id: str, - welcome_message_audio_url: str, account_sid: str, auth_token: str, ) -> dict: @@ -28,7 +26,6 @@ def initiate_call( to_number: Destination phone number from_number: Source phone number (must be a Twilio number) voice_agent_id: ID of the voice agent - welcome_message_audio_url: URL of the welcome message audio file account_sid: Twilio account SID auth_token: Twilio auth token @@ -40,9 +37,7 @@ def initiate_call( client = TwilioClient(account_sid, auth_token) # Build TwiML URL that Twilio will call - # URL-encode the presigned URL to safely pass as query parameter (FastAPI will decode it) - encoded_audio_url = quote(welcome_message_audio_url, safe='') - twiml_url = f'{self.call_processing_base_url}/webhooks/twiml?voice_agent_id={voice_agent_id}&welcome_message_audio_url={encoded_audio_url}' + twiml_url = f'{self.call_processing_base_url}/webhooks/twiml?voice_agent_id={voice_agent_id}' logger.info( f'Initiating call from {from_number} to {to_number} for agent {voice_agent_id}' diff --git a/wavefront/server/modules/voice_agents_module/voice_agents_module/services/voice_agent_service.py b/wavefront/server/modules/voice_agents_module/voice_agents_module/services/voice_agent_service.py index dfb0e4ab..d6e17917 100644 --- a/wavefront/server/modules/voice_agents_module/voice_agents_module/services/voice_agent_service.py +++ b/wavefront/server/modules/voice_agents_module/voice_agents_module/services/voice_agent_service.py @@ -429,19 +429,20 @@ async def create_agent( # Generate agent ID first agent_id = uuid.uuid4() - # Generate and upload welcome message audio BEFORE creating agent - # If this fails, no agent record is created - await self._generate_and_upload_welcome_audio( - welcome_message, - tts_config_id, - tts_voice_ids, - tts_parameters, - agent_id, - supported_languages, - default_language, - ) - - # Create agent only if audio generation succeeded + # Welcome audio generation disabled - pipecat now plays welcome message + # via TTSSpeakFrame in real-time when the WebSocket client connects. + # Keeping _generate_and_upload_welcome_audio() method for future reuse. + # await self._generate_and_upload_welcome_audio( + # welcome_message, + # tts_config_id, + # tts_voice_ids, + # tts_parameters, + # agent_id, + # supported_languages, + # default_language, + # ) + + # Create agent agent = await self.voice_agent_repository.create( id=agent_id, name=name, @@ -649,33 +650,34 @@ async def update_agent(self, agent_id: UUID, **update_data) -> Optional[dict]: logger.error(f'TTS/STT validation failed: {error_message}') raise ValueError(error_message) - # Check if welcome_message or language config changed (requires audio regeneration) - audio_regeneration_needed = False - if ( - 'welcome_message' in update_data - and update_data['welcome_message'] != existing_agent.welcome_message - ): - audio_regeneration_needed = True - if 'supported_languages' in update_data and update_data[ - 'supported_languages' - ] != existing_dict.get('supported_languages'): - audio_regeneration_needed = True - if 'default_language' in update_data and update_data[ - 'default_language' - ] != existing_dict.get('default_language'): - audio_regeneration_needed = True - if 'tts_voice_ids' in update_data and update_data[ - 'tts_voice_ids' - ] != existing_dict.get('tts_voice_ids'): - audio_regeneration_needed = True - if 'tts_parameters' in update_data and update_data[ - 'tts_parameters' - ] != existing_dict.get('tts_parameters'): - audio_regeneration_needed = True - if 'tts_config_id' in update_data and update_data[ - 'tts_config_id' - ] != existing_dict.get('tts_config_id'): - audio_regeneration_needed = True + # Welcome audio regeneration disabled - pipecat now plays welcome message + # via TTSSpeakFrame in real-time when the WebSocket client connects. + # audio_regeneration_needed = False + # if ( + # 'welcome_message' in update_data + # and update_data['welcome_message'] != existing_agent.welcome_message + # ): + # audio_regeneration_needed = True + # if 'supported_languages' in update_data and update_data[ + # 'supported_languages' + # ] != existing_dict.get('supported_languages'): + # audio_regeneration_needed = True + # if 'default_language' in update_data and update_data[ + # 'default_language' + # ] != existing_dict.get('default_language'): + # audio_regeneration_needed = True + # if 'tts_voice_ids' in update_data and update_data[ + # 'tts_voice_ids' + # ] != existing_dict.get('tts_voice_ids'): + # audio_regeneration_needed = True + # if 'tts_parameters' in update_data and update_data[ + # 'tts_parameters' + # ] != existing_dict.get('tts_parameters'): + # audio_regeneration_needed = True + # if 'tts_config_id' in update_data and update_data[ + # 'tts_config_id' + # ] != existing_dict.get('tts_config_id'): + # audio_regeneration_needed = True # If any FK fields are being updated, validate them if any( @@ -708,45 +710,44 @@ async def update_agent(self, agent_id: UUID, **update_data) -> Optional[dict]: logger.error(f'FK validation failed: {error_message}') raise ValueError(error_message) - # Regenerate welcome audio if needed - if audio_regeneration_needed: - logger.info( - 'Welcome message or language config changed, regenerating audio' - ) - try: - # Use updated values if provided, otherwise use existing - welcome_message = update_data.get( - 'welcome_message', existing_agent.welcome_message - ) - tts_config_id = update_data.get( - 'tts_config_id', existing_agent.tts_config_id - ) - tts_voice_ids = update_data.get( - 'tts_voice_ids', existing_agent.tts_voice_ids - ) - tts_parameters = update_data.get( - 'tts_parameters', existing_dict.get('tts_parameters') - ) - supported_languages = update_data.get( - 'supported_languages', - existing_dict.get('supported_languages', ['en']), - ) - default_language = update_data.get( - 'default_language', existing_dict.get('default_language', 'en') - ) - - await self._generate_and_upload_welcome_audio( - welcome_message, - tts_config_id, - tts_voice_ids, - tts_parameters, - agent_id, - supported_languages, - default_language, - ) - except Exception as e: - logger.error(f'Failed to regenerate welcome audio: {str(e)}') - raise e + # Welcome audio regeneration disabled - pipecat handles welcome message now. + # if audio_regeneration_needed: + # logger.info( + # 'Welcome message or language config changed, regenerating audio' + # ) + # try: + # welcome_message = update_data.get( + # 'welcome_message', existing_agent.welcome_message + # ) + # tts_config_id = update_data.get( + # 'tts_config_id', existing_agent.tts_config_id + # ) + # tts_voice_ids = update_data.get( + # 'tts_voice_ids', existing_agent.tts_voice_ids + # ) + # tts_parameters = update_data.get( + # 'tts_parameters', existing_dict.get('tts_parameters') + # ) + # supported_languages = update_data.get( + # 'supported_languages', + # existing_dict.get('supported_languages', ['en']), + # ) + # default_language = update_data.get( + # 'default_language', existing_dict.get('default_language', 'en') + # ) + # + # await self._generate_and_upload_welcome_audio( + # welcome_message, + # tts_config_id, + # tts_voice_ids, + # tts_parameters, + # agent_id, + # supported_languages, + # default_language, + # ) + # except Exception as e: + # logger.error(f'Failed to regenerate welcome audio: {str(e)}') + # raise e updated_agent = await self.voice_agent_repository.find_one_and_update( {'id': agent_id}, refresh=True, **update_data diff --git a/wavefront/server/uv.lock b/wavefront/server/uv.lock index afad6982..f8452ecd 100644 --- a/wavefront/server/uv.lock +++ b/wavefront/server/uv.lock @@ -479,18 +479,18 @@ wheels = [ [[package]] name = "azure-cognitiveservices-speech" -version = "1.44.0" +version = "1.47.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "azure-core" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/0d/0752835f079e8d2cc42bb634f3ccd761c8d6e9d0d46a2d6cf7b3ed8e714c/azure_cognitiveservices_speech-1.44.0-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:78037a147ba72abb57e8c10b693d43a1bb029986fae0918f1f9b7d6342737bfe", size = 7492396, upload-time = "2025-05-19T15:46:11.318Z" }, - { url = "https://files.pythonhosted.org/packages/76/1d/d0ed4ec0f51303a2a532dc845eeb72c7729a3c8639b08050f3c1cd96db79/azure_cognitiveservices_speech-1.44.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2c9b436326cd8dd82dfa88454b7b68359dfc7149e2ac9029f9bcff155ebd5c95", size = 7347577, upload-time = "2025-05-19T15:46:13.644Z" }, - { url = "https://files.pythonhosted.org/packages/89/c8/f0a4ea8bea014b912046f737e429378ceadad68258395454d62acf7f65bb/azure_cognitiveservices_speech-1.44.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:e5f07fc0587067850288c17aebf33d307d2c1ef9e0b2d11d9f44bff2af400568", size = 40977193, upload-time = "2025-05-19T15:46:15.878Z" }, - { url = "https://files.pythonhosted.org/packages/6a/0d/0a0394e8102d6660afeec6b780c451401f6074b1e19f00e90785529e459e/azure_cognitiveservices_speech-1.44.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:3461e22cf04816f69a964d936218d920240f987c0656fdaaf46571529ff0f7e6", size = 40747860, upload-time = "2025-05-19T15:46:19.316Z" }, - { url = "https://files.pythonhosted.org/packages/55/ad/3b7f6eca73040821358ce01f22067446a03d876bfed41cd784291706db4c/azure_cognitiveservices_speech-1.44.0-py3-none-win32.whl", hash = "sha256:a3fe7fd67ba7db281ae490de3d71b5a22648454ec2630eb6a70797f666330586", size = 2164045, upload-time = "2025-05-19T15:46:22.373Z" }, - { url = "https://files.pythonhosted.org/packages/83/ac/f491487d7d0e25ae2929b4f07e7f9b7456feb38e65b36fb605b2c9685b10/azure_cognitiveservices_speech-1.44.0-py3-none-win_amd64.whl", hash = "sha256:77cfb5dd40733b7ccc21edc427e9fb4720997832ea8a1ba460dc94345f3588ae", size = 2422937, upload-time = "2025-05-19T15:46:23.657Z" }, + { url = "https://files.pythonhosted.org/packages/cc/e3/b6a3d1ef4f135f8ef00ed084b9284e65409e9cd52bc96cd0453a5c6637c6/azure_cognitiveservices_speech-1.47.0-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:656577ed01ed4b8cd7c70fab2c921b300181b906f101758a16406bc99b133681", size = 3574346, upload-time = "2025-11-11T21:13:37.717Z" }, + { url = "https://files.pythonhosted.org/packages/82/fa/9cc0c5400e9d433bd98a1239bedf97b34abf410dbc8932a50886ae43e115/azure_cognitiveservices_speech-1.47.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:afd91653ceca482ccea5459eedda1ec9aa95ee07df12a15fc588c42d4f90f0a9", size = 3506219, upload-time = "2025-11-11T21:13:39.702Z" }, + { url = "https://files.pythonhosted.org/packages/6b/d6/b8f55421b8cb40b478f4fb793c52b1bb0ed794263a5475ae2a6490a4cd53/azure_cognitiveservices_speech-1.47.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:577b702ee30d35ecc581e7e2ac23f4387782f93c241d7f8f3c86f72bb883d02d", size = 35399363, upload-time = "2025-11-11T21:13:41.915Z" }, + { url = "https://files.pythonhosted.org/packages/98/91/c36be146824797f57b194128a173baf289a260c2540c86c166f8c7fbebe3/azure_cognitiveservices_speech-1.47.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:ff72c74abe4b4c0f5a527eabf8511a8c0e689d884a95c54a46495b293e302e73", size = 35196906, upload-time = "2025-11-11T21:13:45.31Z" }, + { url = "https://files.pythonhosted.org/packages/fb/19/dd6f08dc623f2b336cc9cd5cf765712df5262fd675583e701922491e455d/azure_cognitiveservices_speech-1.47.0-py3-none-win_amd64.whl", hash = "sha256:ecfce57d66907afe305fb2950cc781ea8f327274facd2db66950e701b6cfd715", size = 2182376, upload-time = "2025-11-11T21:13:47.753Z" }, + { url = "https://files.pythonhosted.org/packages/1b/16/a6d1f7ab7eae21b00da2eee7186a7db9c9a2434e0ef833f071ff686b833f/azure_cognitiveservices_speech-1.47.0-py3-none-win_arm64.whl", hash = "sha256:4351734cf240d11340a057ecb388397e5ecf40e97e4b67a6a990fffe2791b56c", size = 1978493, upload-time = "2025-11-11T21:13:49.445Z" }, ] [[package]] @@ -640,7 +640,7 @@ requires-dist = [ { name = "dependency-injector", specifier = ">=4.46.0,<5.0.0" }, { name = "fastapi", specifier = ">=0.115.2,<1.0.0" }, { name = "httpx", specifier = ">=0.27.0" }, - { name = "pipecat-ai", extras = ["websocket", "cartesia", "google", "silero", "deepgram", "groq", "runner", "azure", "local-smart-turn-v3", "sarvam"], specifier = "==0.0.100" }, + { name = "pipecat-ai", extras = ["websocket", "cartesia", "google", "silero", "deepgram", "groq", "runner", "azure", "local-smart-turn-v3", "sarvam"], specifier = "==0.0.102" }, { name = "pydantic", specifier = ">=2.0.0" }, { name = "python-dotenv", specifier = ">=1.1.0,<2.0.0" }, { name = "python-multipart", specifier = ">=0.0.9" }, @@ -3897,7 +3897,7 @@ wheels = [ [[package]] name = "pipecat-ai" -version = "0.0.100" +version = "0.0.102" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiofiles" }, @@ -3909,6 +3909,7 @@ dependencies = [ { name = "nltk" }, { name = "numba" }, { name = "numpy" }, + { name = "onnxruntime" }, { name = "openai" }, { name = "pillow" }, { name = "protobuf" }, @@ -3916,11 +3917,12 @@ dependencies = [ { name = "pyloudnorm" }, { name = "resampy" }, { name = "soxr" }, + { name = "transformers" }, { name = "wait-for2", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/53/e9/f377fe49617721d41e3f6d563069849d6d1047c7b4cf4e6dfcb143a868a5/pipecat_ai-0.0.100.tar.gz", hash = "sha256:028a6203094f182461f8065a9c5fd92180038826a52ef1322dac2e258190f9f2", size = 10855536, upload-time = "2026-01-21T03:36:59.613Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/61/60a6f7ff2424f9ea6e70c127ece28da241baf3e40b0b5bd6f196bd63a623/pipecat_ai-0.0.102.tar.gz", hash = "sha256:c999d2f0668ab11520396c445605d4eefa1e9bb1965362a52d3dcf3635890519", size = 10957064, upload-time = "2026-02-11T02:33:07.303Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6c/23/4f77c613fdcd5a581a5df0227bfd6e8554151e3f5a423c1e4b2a42b6d3d5/pipecat_ai-0.0.100-py3-none-any.whl", hash = "sha256:1f832329dcb0f5d26f0a478df3a40007b1d3032c9b84f66d3f80225bb59d2f30", size = 10539423, upload-time = "2026-01-21T03:36:56.974Z" }, + { url = "https://files.pythonhosted.org/packages/c0/72/2222f4208dc7eca15cdb174c9fe6303c795d60938f3122b15cfb25397d69/pipecat_ai-0.0.102-py3-none-any.whl", hash = "sha256:b533854d8b720860f8ddeb8a6557a1846a46d4226c0d2f42cb631f7dcf457a8b", size = 10611114, upload-time = "2026-02-11T02:33:04.652Z" }, ] [package.optional-dependencies] @@ -3968,14 +3970,14 @@ websocket = [ [[package]] name = "pipecat-ai-small-webrtc-prebuilt" -version = "2.0.4" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "fastapi", extra = ["all"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2e/88/57b26547ec45623718f1d5beb9e004dba55b7ab548a3b48748466e3e1769/pipecat_ai_small_webrtc_prebuilt-2.0.4.tar.gz", hash = "sha256:3c3447679007ea937c760223bb66579f2605cf94628a68c9da1d66787a96caad", size = 584994, upload-time = "2025-12-30T19:14:52.655Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4a/8b/c945a27503560d50c56f497e43209f43c81616ede5d3d2b38eeb4044dbbc/pipecat_ai_small_webrtc_prebuilt-2.1.0.tar.gz", hash = "sha256:c883304a159dee01eec74b162e51352b32c362ca19d281226a71d92b5ba1c600", size = 596971, upload-time = "2026-02-05T17:01:08.074Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/6e/332b78d1c7888ff426bd528b150aad0da05024f4f91e56502c359726c07b/pipecat_ai_small_webrtc_prebuilt-2.0.4-py3-none-any.whl", hash = "sha256:054b3cee843fe69191859dbb0693560d9ca08f7d57a9ff0457d0bc741f36f4df", size = 585606, upload-time = "2025-12-30T19:14:50.595Z" }, + { url = "https://files.pythonhosted.org/packages/8e/f6/5754d86d513822fb4466549eb6bca05c7246676f1b5b199c9646a5475182/pipecat_ai_small_webrtc_prebuilt-2.1.0-py3-none-any.whl", hash = "sha256:0882d147f69d8cc07397ee68b75c554f4d2d75d8023207e7fb86760616bc58aa", size = 597535, upload-time = "2026-02-05T17:01:06.622Z" }, ] [[package]] @@ -4174,16 +4176,16 @@ wheels = [ [[package]] name = "protobuf" -version = "5.29.5" +version = "5.29.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/29/d09e70352e4e88c9c7a198d5645d7277811448d76c23b00345670f7c8a38/protobuf-5.29.5.tar.gz", hash = "sha256:bc1463bafd4b0929216c35f437a8e28731a2b7fe3d98bb77a600efced5a15c84", size = 425226, upload-time = "2025-05-28T23:51:59.82Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/57/394a763c103e0edf87f0938dafcd918d53b4c011dfc5c8ae80f3b0452dbb/protobuf-5.29.6.tar.gz", hash = "sha256:da9ee6a5424b6b30fd5e45c5ea663aef540ca95f9ad99d1e887e819cdf9b8723", size = 425623, upload-time = "2026-02-04T22:54:40.584Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/11/6e40e9fc5bba02988a214c07cf324595789ca7820160bfd1f8be96e48539/protobuf-5.29.5-cp310-abi3-win32.whl", hash = "sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079", size = 422963, upload-time = "2025-05-28T23:51:41.204Z" }, - { url = "https://files.pythonhosted.org/packages/81/7f/73cefb093e1a2a7c3ffd839e6f9fcafb7a427d300c7f8aef9c64405d8ac6/protobuf-5.29.5-cp310-abi3-win_amd64.whl", hash = "sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc", size = 434818, upload-time = "2025-05-28T23:51:44.297Z" }, - { url = "https://files.pythonhosted.org/packages/dd/73/10e1661c21f139f2c6ad9b23040ff36fee624310dc28fba20d33fdae124c/protobuf-5.29.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e38c5add5a311f2a6eb0340716ef9b039c1dfa428b28f25a7838ac329204a671", size = 418091, upload-time = "2025-05-28T23:51:45.907Z" }, - { url = "https://files.pythonhosted.org/packages/6c/04/98f6f8cf5b07ab1294c13f34b4e69b3722bb609c5b701d6c169828f9f8aa/protobuf-5.29.5-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:fa18533a299d7ab6c55a238bf8629311439995f2e7eca5caaff08663606e9015", size = 319824, upload-time = "2025-05-28T23:51:47.545Z" }, - { url = "https://files.pythonhosted.org/packages/85/e4/07c80521879c2d15f321465ac24c70efe2381378c00bf5e56a0f4fbac8cd/protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:63848923da3325e1bf7e9003d680ce6e14b07e55d0473253a690c3a8b8fd6e61", size = 319942, upload-time = "2025-05-28T23:51:49.11Z" }, - { url = "https://files.pythonhosted.org/packages/7e/cc/7e77861000a0691aeea8f4566e5d3aa716f2b1dece4a24439437e41d3d25/protobuf-5.29.5-py3-none-any.whl", hash = "sha256:6cf42630262c59b2d8de33954443d94b746c952b01434fc58a417fdbd2e84bd5", size = 172823, upload-time = "2025-05-28T23:51:58.157Z" }, + { url = "https://files.pythonhosted.org/packages/d4/88/9ee58ff7863c479d6f8346686d4636dd4c415b0cbeed7a6a7d0617639c2a/protobuf-5.29.6-cp310-abi3-win32.whl", hash = "sha256:62e8a3114992c7c647bce37dcc93647575fc52d50e48de30c6fcb28a6a291eb1", size = 423357, upload-time = "2026-02-04T22:54:25.805Z" }, + { url = "https://files.pythonhosted.org/packages/1c/66/2dc736a4d576847134fb6d80bd995c569b13cdc7b815d669050bf0ce2d2c/protobuf-5.29.6-cp310-abi3-win_amd64.whl", hash = "sha256:7e6ad413275be172f67fdee0f43484b6de5a904cc1c3ea9804cb6fe2ff366eda", size = 435175, upload-time = "2026-02-04T22:54:28.592Z" }, + { url = "https://files.pythonhosted.org/packages/06/db/49b05966fd208ae3f44dcd33837b6243b4915c57561d730a43f881f24dea/protobuf-5.29.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:b5a169e664b4057183a34bdc424540e86eea47560f3c123a0d64de4e137f9269", size = 418619, upload-time = "2026-02-04T22:54:30.266Z" }, + { url = "https://files.pythonhosted.org/packages/b7/d7/48cbf6b0c3c39761e47a99cb483405f0fde2be22cf00d71ef316ce52b458/protobuf-5.29.6-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:a8866b2cff111f0f863c1b3b9e7572dc7eaea23a7fae27f6fc613304046483e6", size = 320284, upload-time = "2026-02-04T22:54:31.782Z" }, + { url = "https://files.pythonhosted.org/packages/e3/dd/cadd6ec43069247d91f6345fa7a0d2858bef6af366dbd7ba8f05d2c77d3b/protobuf-5.29.6-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:e3387f44798ac1106af0233c04fb8abf543772ff241169946f698b3a9a3d3ab9", size = 320478, upload-time = "2026-02-04T22:54:32.909Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cb/e3065b447186cb70aa65acc70c86baf482d82bf75625bf5a2c4f6919c6a3/protobuf-5.29.6-py3-none-any.whl", hash = "sha256:6b9edb641441b2da9fa8f428760fc136a49cf97a52076010cf22a2ff73438a86", size = 173126, upload-time = "2026-02-04T22:54:39.462Z" }, ] [[package]]