Skip to content

Conversation

@rootflo-hardik
Copy link
Contributor

@rootflo-hardik rootflo-hardik commented Jan 12, 2026

Summary by CodeRabbit

  • New Features

    • Added multi-language support for voice agents with language selection, detection, and language-aware audio generation
    • Added inbound and outbound phone number configuration at the agent level
    • Added TTS voice selection per agent
    • Introduced inbound call routing to agents by phone number
  • Improvements

    • Simplified configuration by centralizing phone numbers and language settings to the agent level

✏️ Tip: You can customize this high-level summary in your review settings.

- added alembic migration for removing phone_numbers from telephony_config, having inbound outbound numbers, supported default languages in voice_agents
- respective changes in service, controller files
- added phone and language validation
@coderabbitai
Copy link

coderabbitai bot commented Jan 12, 2026

📝 Walkthrough

Walkthrough

This PR adds multi-language voice agent support and restructures configuration management. Language support is introduced at the agent level with supported_languages and default_language fields, language detection capabilities, and inbound call handling via phone number-based agent lookup. TTS/STT configuration is simplified by moving language and parameters from config tables to voice agents. Phone number management is relocated from telephony configs to agent records. A database migration consolidates configuration data into the voice_agent table.

Changes

Cohort / File(s) Summary
Language Support Constants
wavefront/client/src/constants/languages.ts
New TypeScript module defining LanguageOption interface, SUPPORTED_LANGUAGES list, and utility functions getLanguageName() and getLanguageDisplayName() for language code lookup and display formatting.
Voice Agent Form Dialogs (Create)
wavefront/client/src/pages/apps/[appId]/voice-agents/CreateVoiceAgentDialog.tsx
Added TTS/STT parameter state management, dynamic parameter field rendering, multi-select language configuration with checkboxes, phone number validation (E.164 format), and tts_voice_id input. Extended schema with tts_voice_id, inbound_numbers, outbound_numbers, supported_languages, default_language.
Voice Agent Form Dialogs (Edit)
wavefront/client/src/pages/apps/[appId]/voice-agents/EditVoiceAgentDialog.tsx
Mirror of Create dialog enhancements; adds provider-aware TTS/STT parameter UI, language/phone configuration sections, validates default_language within supported_languages, constructs partial update payload with new fields.
Voice Agent Outbound Call Dialog
wavefront/client/src/pages/apps/[appId]/voice-agents/OutboundCallDialog.tsx
Removed appId prop; changed phone number source from telephony config to agent.outbound_numbers.
Voice Agent List View
wavefront/client/src/pages/apps/[appId]/voice-agents/index.tsx
Added table columns for inbound_numbers count, outbound_numbers count, and languages (with tooltips). Removed appId prop from OutboundCallDialog invocation.
STT Config Dialogs
wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/(Create|Edit)SttConfigDialog.tsx, index.tsx
Removed language field, dynamic parameters UI, and provider-driven parameter rendering. Simplified payloads to display_name, description, provider, api_key only. Removed Language column from table.
TTS Config Dialogs
wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/(Create|Edit)TtsConfigDialog.tsx, index.tsx
Removed voice_id, language, and parameters fields; removed dynamic parameter UI. Disabled provider field in edit (read-only). Removed Voice ID and Language columns from table.
Telephony Config Dialogs
wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/(Create|Edit)TelephonyConfigDialog.tsx, index.tsx
Removed phone number input UI, validation logic, and phone_numbers payload. Removed Phone Numbers column from table.
Type Definitions (Frontend)
wavefront/client/src/types/voice-agent.ts, stt-config.ts, tts-config.ts, telephony-config.ts
Updated VoiceAgent to include tts_voice_id, tts_parameters, stt_parameters, inbound_numbers, outbound_numbers, supported_languages, default_language. Removed language and parameters from STT/TTS config types; removed phone_numbers from telephony config types.
Language Configuration (Backend)
wavefront/server/apps/call_processing/.../constants/language_config.py
New module defining LANGUAGE_KEYWORDS (language code to keywords mapping) and LANGUAGE_INSTRUCTIONS (language code to instruction prompts) for language detection.
Cache & Webhook Controllers (Backend)
wavefront/server/apps/call_processing/.../controllers/cache_controller.py
Changed InvalidateCacheRequest.config_id from UUID to str; added inbound_number cache type support with immediate cache removal before Floware contact.
Webhook Endpoints (Backend)
wavefront/server/apps/call_processing/.../controllers/webhook_controller.py
Added new POST /inbound endpoint for Twilio inbound calls; looks up agent by phone number, fetches welcome message URL, constructs WebSocket with voice_agent_id. Extended POST /twiml to accept welcome_message_audio_url query parameter.
Floware HTTP Client (Backend)
wavefront/server/apps/call_processing/.../services/floware_http_client.py
Added get_agent_by_inbound_number(phone_number) and get_welcome_message_audio_url(agent_id) methods with graceful 404 handling.
Pipecat Service (Backend)
wavefront/server/apps/call_processing/.../services/pipecat_service.py
Introduced multi-language support with per-language STT/TTS service instantiation, ServiceSwitcher for manual language switching, TranscriptProcessor-based language detection from user messages, dynamic LLM system prompt injection with language instructions. Increased interruption threshold from 2 to 3 words.
Voice Agent Cache Service (Backend)
wavefront/server/apps/call_processing/.../services/voice_agent_cache_service.py
Added get_agent_by_inbound_number(phone_number) with cache-first strategy and get_welcome_message_audio_url(agent_id) with 2-hour URL cache TTL.
Database Migration (Backend)
wavefront/server/modules/db_repo_module/.../alembic/versions/2026_01_08_1547-*.py
Migration adds voice_agent columns (inbound_numbers, outbound_numbers, supported_languages, default_language, tts_voice_id, tts_parameters, stt_parameters); migrates TTS/STT data from configs to agent; drops language/parameters from tts_configs and stt_configs; drops phone_numbers from telephony_configs. Reversible downgrade.
Database Models (Backend)
wavefront/server/modules/db_repo_module/.../models/voice_agent.py, stt_config.py, tts_config.py, telephony_config.py
Added 7 new JSONB/string columns to VoiceAgent with JSON parsing in to_dict(). Removed language and parameters from SttConfig, voice_id/language/parameters from TtsConfig, phone_numbers from TelephonyConfig. Enhanced JSON field handling in to_dict() methods.
API Schemas (Backend)
wavefront/server/modules/voice_agents_module/.../models/(voice_agent|stt|tts|telephony)_schemas.py
Updated VoiceAgentPayload/Response to include new 7 fields. Removed language/parameters from STT payloads and responses. Removed voice_id/language/parameters from TTS update payload and responses. Removed phone_numbers from telephony payloads and responses.
API Controllers (Backend)
wavefront/server/modules/voice_agents_module/.../controllers/voice_agent_controller.py
Extended create_voice_agent and update_voice_agent with new fields. Added GET /v1/voice-agents/by-inbound-number/{phone_number} and GET /v1/voice-agents/{agent_id}/welcome-audio-url endpoints. Reworked initiate_call to use agent.outbound_numbers instead of telephony config phone_numbers.
Config Controllers (Backend)
wavefront/server/modules/voice_agents_module/.../controllers/(stt|tts|telephony)_config_controller.py
Removed language/parameters handling from STT and TTS creation/updates. Removed phone_numbers from telephony config. Simplified payload processing.
Service Layer (Backend)
wavefront/server/modules/voice_agents_module/.../services/(stt|tts|telephony)_config_service.py
Removed language/parameters parameters from create_config methods. Simplified stored config data.
Voice Agent Service (Backend)
wavefront/server/modules/voice_agents_module/.../services/voice_agent_service.py
Added _validate_tts_stt_parameters(), _validate_language_and_phone_config(), _generate_and_upload_welcome_audio(), _invalidate_inbound_number_cache(), and get_agent_by_inbound_number(). Extended create_agent and update_agent with language/phone validation, audio regeneration on config changes, inbound cache management.
Validation Utilities (Backend)
wavefront/server/modules/voice_agents_module/.../utils/language_validation.py, phone_validation.py
New modules: language_validation provides language name mappings, provider-specific language sets (ElevenLabs, Cartesia, Deepgram), and validation functions for language support and default language. phone_validation provides E.164 regex pattern and phone number list validation.
Cache Utilities (Backend)
wavefront/server/modules/voice_agents_module/.../utils/cache_invalidation.py, cache_utils.py
cache_invalidation: changed config_id param type UUID → UUID|str to support inbound_number type. cache_utils: added get_inbound_number_cache_key(phone_number) function.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant Twilio
    participant Webhook as Webhook/Inbound
    participant CacheService as Voice Agent Cache
    participant FlowareAPI as Floware API
    participant PipecatService as Pipecat Service
    participant LLM

    Caller->>Twilio: Call to phone number
    Twilio->>Webhook: POST /inbound with From/To/CallSid
    Webhook->>CacheService: get_agent_by_inbound_number(To)
    CacheService->>CacheService: Check cache for inbound number
    alt Cache hit with agent ID
        CacheService->>FlowareAPI: GET full agent data
    else Cache miss
        CacheService->>FlowareAPI: GET agent by inbound number
        FlowareAPI-->>CacheService: Return agent data
    end
    CacheService-->>Webhook: Voice agent config

    Webhook->>CacheService: get_welcome_message_audio_url(agent_id)
    CacheService->>FlowareAPI: GET presigned welcome audio URL
    FlowareAPI-->>CacheService: URL (or empty if not exists)
    CacheService-->>Webhook: Welcome audio URL
    
    Webhook-->>Twilio: TwiML response with WebSocket URL
    Twilio-->>Caller: Play welcome message + open WebSocket
    
    Caller->>PipecatService: Audio stream via WebSocket
    PipecatService->>PipecatService: Detect language from first user message
    alt Multi-language enabled
        PipecatService->>PipecatService: Switch STT/TTS to detected language
    end
    PipecatService->>LLM: Send message with language-specific system prompt
    LLM-->>PipecatService: Response
    PipecatService-->>Caller: TTS audio in detected language
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • vizsatiz
  • vishnurk6247

Poem

🐰 Hops with delight at languages galore!
Phone numbers now rest where agents adore,
TTS and STT find freedom anew,
Inbound calls ring, detected in queue,
Parameters flutter like carrots in flight—
The agent's sweet kingdom now shines ever bright! 🌟

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 84.91% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The PR title clearly and specifically describes the primary additions: inbound voice agent support, language detection, and configuration management.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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 and usage tips.

from sqlalchemy import text

# revision identifiers, used by Alembic.
revision: str = '6010e49da528'

# revision identifiers, used by Alembic.
revision: str = '6010e49da528'
down_revision: Union[str, None] = 'f7572bcd9510'
# revision identifiers, used by Alembic.
revision: str = '6010e49da528'
down_revision: Union[str, None] = 'f7572bcd9510'
branch_labels: Union[str, Sequence[str], None] = None
revision: str = '6010e49da528'
down_revision: Union[str, None] = 'f7572bcd9510'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/EditSttConfigDialog.tsx (1)

33-38: Schema and provider list mismatch may cause validation failures for existing configs.

The schema hardcodes provider: z.enum(['deepgram']) while the UI renders all providers from VOICE_PROVIDERS_CONFIG.stt.providers. If an existing config uses a different provider (e.g., from legacy data or the SttProvider enum includes assemblyai, whisper, google, azure), the form will fail validation when opened.

Consider either:

  1. Matching the schema to the server's SttProvider enum values, or
  2. Using a dynamic enum based on the config's actual provider value
Option 1: Match server enum values
 const updateSttConfigSchema = z.object({
   display_name: z.string().min(1, 'Display name is required').max(100, 'Display name must be 100 characters or less'),
   description: z.string().max(500, 'Description must be 500 characters or less').optional(),
-  provider: z.enum(['deepgram'] as [string, ...string[]]),
+  provider: z.enum(['deepgram', 'assemblyai', 'whisper', 'google', 'azure'] as [string, ...string[]]),
   api_key: z.string().optional(),
 });
wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/CreateSttConfigDialog.tsx (1)

32-37: Provider selection and validation mismatch will cause UX issues.

The schema on line 35 only allows 'deepgram', but the Select component (lines 136-143) renders all providers from VOICE_PROVIDERS_CONFIG.stt.providers. If this config includes other providers, users can select them but the form will fail zod validation.

Either restrict the Select options to match the schema, or expand the schema to match available providers.

Option 1: Restrict Select to only show 'deepgram'
 <SelectContent>
-  {VOICE_PROVIDERS_CONFIG.stt.providers.map((p) => {
-    const config = getProviderConfig('stt', p);
-    return (
-      <SelectItem key={p} value={p}>
-        {config?.name || p}
-      </SelectItem>
-    );
-  })}
+  <SelectItem value="deepgram">
+    {getProviderConfig('stt', 'deepgram')?.name || 'Deepgram'}
+  </SelectItem>
 </SelectContent>
Option 2: Expand schema to match VOICE_PROVIDERS_CONFIG

If multiple providers should be supported, update the schema to accept all provider values dynamically or list them explicitly.

Also applies to: 129-149

🤖 Fix all issues with AI agents
In @wavefront/client/src/pages/apps/[appId]/voice-agents/index.tsx:
- Around line 156-163: The count fallback currently uses
agent.supported_languages?.length || 1 which incorrectly shows "1" when
supported_languages is undefined or empty; update the span to show a truthful
empty state by using agent.supported_languages?.length ?? 0 (or render a dash
'-') and keep the title safe by guarding the join (e.g.,
title={agent.supported_languages?.map(getLanguageName).join(', ') || '-'}) so
the TableCell/span displays 0 or '-' when no languages exist and still shows the
default_language (agent.default_language || 'en') as before.

In
@wavefront/server/apps/call_processing/call_processing/constants/language_config.py:
- Around line 33-34: The language alias mapping contains overlapping entries for
'fil' and 'tl' (both include 'tagalog'/'filipino'), causing non-deterministic
detection; update the language aliases dict (the mapping that defines 'fil' and
'tl') to remove the ambiguity by either consolidating into a single canonical
code (e.g., keep only 'fil' and drop the 'tl' key) or by making their keyword
lists mutually exclusive (give each key unique trigger words), and update any
related comments/tests that reference 'fil' or 'tl' to reflect the new canonical
choice.

In
@wavefront/server/modules/db_repo_module/db_repo_module/alembic/versions/2026_01_08_1547-6010e49da528_add_inbound_voice_agent_support.py:
- Around line 152-178: The downgrade currently restores columns but fails to
repopulate them from the new voice_agents table, causing data loss; update
downgrade() to migrate data back before dropping voice_agents columns by: after
adding back columns (tts_configs.voice_id, tts_configs.parameters,
stt_configs.language, stt_configs.parameters, telephony_configs.phone_numbers)
run SQL updates (via op.execute) that join voice_agents to
tts_configs/stt_configs/telephony_configs and set the restored columns from
voice_agents.tts_voice_id, voice_agents.tts_parameters,
voice_agents.stt_parameters, voice_agents.default_language (and
supported_languages/outbound_numbers/inbound_numbers as appropriate), then only
drop the columns from voice_agents; alternatively document this as irreversible
if you decide not to implement the reverse migration.

In
@wavefront/server/modules/voice_agents_module/voice_agents_module/utils/language_validation.py:
- Around line 52-171: ELEVENLABS_LANGUAGES contains entries that don't match the
eleven_multilingual_v2 model; update ELEVENLABS_LANGUAGES to exactly reflect
ElevenLabs' supported languages (remove 'hi', 'no', 'vi' or any other
unsupported codes) or add a verification step that checks the configured
language against the live ElevenLabs model before use; locate and edit the
ELEVENLABS_LANGUAGES constant in language_validation.py and ensure any caller
(e.g., functions that reference ELEVENLABS_LANGUAGES) fails fast with a clear
error if an unsupported language is requested.
🧹 Nitpick comments (23)
wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/index.tsx (1)

78-86: LGTM - Filter updated correctly for the schema change.

The addition of connection_type to the search filter is appropriate given the removal of phone numbers from telephony configs.

One minor note: description has a null guard (line 82), while connection_type does not. If connection_type is guaranteed to be non-null by the TelephonyConfig type, this is fine. Otherwise, consider adding a similar guard for defensive consistency:

-      config.connection_type.toLowerCase().includes(query)
+      (config.connection_type && config.connection_type.toLowerCase().includes(query))
wavefront/server/modules/voice_agents_module/voice_agents_module/services/tts_config_service.py (1)

37-43: Type hints use incorrect default None pattern.

Parameters provider and api_key have str = None which is technically incorrect—None is not a valid str. Use Optional[str] for clarity and type checker compatibility.

Suggested fix
     async def create_config(
         self,
         display_name: str,
         description: Optional[str] = None,
-        provider: str = None,
-        api_key: str = None,
+        provider: Optional[str] = None,
+        api_key: Optional[str] = None,
     ) -> dict:
wavefront/server/modules/db_repo_module/db_repo_module/models/voice_agent.py (1)

71-100: Consider consolidating field name lists for maintainability.

The array field names appear in two places (lines 71-78 and 93-98). If new JSONB fields are added later, both lists must be updated. Consider extracting to class-level constants.

Suggested approach
# At class level
_JSONB_FIELDS = frozenset({
    'conversation_config', 'inbound_numbers', 'outbound_numbers',
    'supported_languages', 'tts_parameters', 'stt_parameters',
})
_JSONB_ARRAY_FIELDS = frozenset({
    'inbound_numbers', 'outbound_numbers', 'supported_languages',
})

# Then in to_dict:
elif column.name in self._JSONB_FIELDS:
    # ...
    result[column.name] = [] if column.name in self._JSONB_ARRAY_FIELDS else None
wavefront/server/modules/db_repo_module/db_repo_module/alembic/versions/2026_01_08_1547-6010e49da528_add_inbound_voice_agent_support.py (1)

70-94: Row-by-row migration may be slow for large tables.

The Python loop processes each agent individually with separate UPDATE statements. For large datasets, this could be slow. Consider a single SQL UPDATE with subquery if performance is a concern.

Alternative batch approach
UPDATE voice_agents va
SET
    tts_voice_id = COALESCE(tc.voice_id, 'default'),
    tts_parameters = COALESCE(tc.parameters::jsonb, '{}'::jsonb),
    stt_parameters = COALESCE(sc.parameters::jsonb, '{}'::jsonb)
FROM tts_configs tc, stt_configs sc
WHERE va.tts_config_id = tc.id
  AND va.stt_config_id = sc.id
  AND va.is_deleted = false;

This performs the migration in a single statement. The safety fallback at lines 98-102 would still catch any remaining NULLs.

wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/tts_config_controller.py (1)

22-48: Unused request parameter.

The request: Request parameter on line 23 is not used within the function body. If it's no longer needed after the refactoring, consider removing it to keep the function signature clean.

Suggested fix
 @tts_config_router.post('/v1/tts-configs')
 @inject
 async def create_tts_config(
-    request: Request,
     payload: CreateTtsConfigPayload,
     response_formatter: ResponseFormatter = Depends(
         Provide[CommonContainer.response_formatter]
     ),

Also remove Request from the imports on line 4 if no longer used elsewhere.

wavefront/server/apps/call_processing/call_processing/controllers/cache_controller.py (2)

107-114: Consider unpacking for list construction.

Minor style improvement suggested by static analysis.

Proposed fix
-    valid_types = list(VALID_CONFIG_TYPES) + ['inbound_number']
+    valid_types = [*VALID_CONFIG_TYPES, 'inbound_number']

140-147: Chain the exception for better debugging.

The raise statement should include from to preserve the original exception context per Python best practices.

Proposed fix
     try:
         config_id = UUID(config_id_str)
     except ValueError:
         logger.error(f'Invalid UUID format for config_id: {config_id_str}')
         raise HTTPException(
             status_code=status.HTTP_400_BAD_REQUEST,
             detail=f'config_id must be a valid UUID for config_type={config_type}',
-        )
+        ) from None

Using from None explicitly suppresses the chained exception if you don't want users to see the internal ValueError, or use from e (where e is the caught exception) if you want full chaining.

wavefront/server/apps/call_processing/call_processing/services/floware_http_client.py (1)

127-171: Consider URL-encoding the phone number for RFC 3986 compliance.

While the + character in URL paths is not converted to space (that only happens in query strings), RFC 3986 specifies that special characters in URLs should be percent-encoded. The backend's FastAPI endpoint handles raw path parameters correctly, but encoding ensures robustness across different proxies, load balancers, and URL parsing implementations.

Suggested approach
+from urllib.parse import quote
+
     async def get_agent_by_inbound_number(
         self, phone_number: str
     ) -> Optional[Dict[str, Any]]:
         ...
         url = (
-            f'{self.base_url}/floware/v1/voice-agents/by-inbound-number/{phone_number}'
+            f'{self.base_url}/floware/v1/voice-agents/by-inbound-number/{quote(phone_number, safe="")}'
         )

If the server explicitly expects raw phone numbers without encoding, document that assumption and confirm it handles E.164 format correctly.

wavefront/server/apps/call_processing/call_processing/services/voice_agent_cache_service.py (1)

385-386: Consider extracting the TTL magic number to a named constant.

The value 7100 seconds (~2 hours) is hardcoded. For maintainability, consider defining it as a class constant alongside self.cache_ttl:

WELCOME_URL_TTL = 7100  # ~2 hours, matches floware presigned URL expiry
wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/EditTtsConfigDialog.tsx (1)

63-73: Potential unnecessary re-renders from form in dependency array.

Including form in the useEffect dependency array (line 73) can cause the effect to run more often than intended if the form object reference changes. Since form comes from useForm() hook, its reference should be stable, but for clarity and to avoid potential issues:

♻️ Suggested fix
   useEffect(() => {
     if (isOpen && config) {
       form.reset({
         display_name: config.display_name,
         description: config.description || '',
         provider: config.provider,
         api_key: '',
       });
     }
-  }, [isOpen, config, form]);
+  }, [isOpen, config, form.reset]);
wavefront/server/apps/call_processing/call_processing/controllers/webhook_controller.py (2)

86-97: Consider extracting duplicate URL conversion logic.

The WebSocket URL construction logic (lines 86-97) is duplicated in twiml_endpoint (lines 148-159). Consider extracting this into a helper function.

♻️ Suggested refactor
def _build_websocket_url() -> str:
    """Build WebSocket URL from base URL environment variable."""
    base_url = os.getenv('CALL_PROCESSING_BASE_URL', 'http://localhost:8003')
    
    if base_url.startswith('https://'):
        websocket_url = base_url.replace('https://', 'wss://')
    elif base_url.startswith('http://'):
        websocket_url = base_url.replace('http://', 'ws://')
    else:
        websocket_url = f'wss://{base_url}'
    
    return f'{websocket_url}/webhooks/ws'

116-116: Agent ID should be converted to string explicitly.

agent_id is extracted from agent['id'] which could be a UUID object. Twilio stream parameters expect string values. Ensure consistent string conversion.

♻️ Proposed fix
-    stream.parameter(name='voice_agent_id', value=agent_id)
+    stream.parameter(name='voice_agent_id', value=str(agent_id))
wavefront/client/src/pages/apps/[appId]/voice-agents/EditVoiceAgentDialog.tsx (2)

339-536: Consider consolidating TTS and STT parameter rendering functions.

renderTtsParameterField (lines 339-436) and renderSttParameterField (lines 439-536) are nearly identical, differing only in state variables and IDs. Consider extracting a shared function.

♻️ Suggested approach
const renderParameterField = (
  type: 'tts' | 'stt',
  key: string,
  provider: string | undefined,
  parameters: Record<string, unknown>,
  setParameter: (key: string, value: unknown) => void
) => {
  if (!provider) return null;
  const config = getProviderConfig(type, provider);
  if (!config) return null;
  
  const paramConfig = config.parameters[key];
  if (!paramConfig) return null;
  
  // ... shared rendering logic with dynamic id prefix
};

// Usage:
{Object.keys(ttsProviderConfig.parameters)
  .filter((key) => key !== 'language')
  .map((key) => renderParameterField('tts', key, selectedTtsProvider, ttsParameters, setTtsParameter))}

853-858: Default language checkbox may become invalid when supported languages change.

When a user unchecks a language that is currently set as the default language, the dropdown will no longer show that option, but the form value remains set. The validation at line 227-230 catches this on submit, but this could confuse users.

Consider resetting default_language to the first remaining supported language when the current default is removed from supported_languages.

wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py (2)

321-322: Unused processor argument in event handler.

The processor parameter is declared but never used in the handler function. If not needed by the event handler contract, consider removing it or using _ to indicate intentionally unused.

♻️ Proposed fix
             @transcript.event_handler('on_transcript_update')
-            async def handle_language_detection(processor, frame):
+            async def handle_language_detection(_processor, frame):
                 """Detect language from first user message and switch services"""

428-428: Use list unpacking instead of concatenation for better performance.

As flagged by static analysis, prefer list unpacking over concatenation.

♻️ Proposed fix
-                        new_messages = [updated_system_message] + current_messages[1:]
+                        new_messages = [updated_system_message, *current_messages[1:]]
wavefront/client/src/pages/apps/[appId]/voice-agents/CreateVoiceAgentDialog.tsx (2)

277-487: Significant code duplication with EditVoiceAgentDialog.

The renderTtsParameterField and renderSttParameterField functions (lines 277-487) are nearly identical to those in EditVoiceAgentDialog.tsx. The same applies to phone number parsing/validation and language configuration UI.

Consider extracting shared logic into:

  1. A shared parameter rendering utility or hook
  2. A shared phone number validation utility
  3. Common form field components for the language configuration section

808-813: Same UX issue with default language selection as in EditVoiceAgentDialog.

When a user unchecks a language that is currently set as the default, the dropdown becomes empty but the form value remains. Consider adding an effect to auto-reset default_language when it's no longer in supported_languages.

♻️ Suggested addition
// Add this useEffect after the form definition
const watchedSupportedLanguages = form.watch('supported_languages');
const watchedDefaultLanguage = form.watch('default_language');

useEffect(() => {
  if (watchedSupportedLanguages && !watchedSupportedLanguages.includes(watchedDefaultLanguage)) {
    // Reset to first supported language or 'en' as fallback
    const newDefault = watchedSupportedLanguages[0] || 'en';
    form.setValue('default_language', newDefault);
  }
}, [watchedSupportedLanguages, watchedDefaultLanguage, form]);
wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/voice_agent_controller.py (2)

501-516: Missing agent existence validation before generating welcome audio URL.

The get_welcome_audio_url endpoint calls voice_agent_service.get_welcome_message_audio_url(agent_id) directly without first verifying the agent exists. If the agent doesn't exist or has no welcome message, the error will be generic. Consider adding an agent existence check for a better error response.

♻️ Proposed fix
 async def get_welcome_audio_url(
     agent_id: UUID = Path(..., description='The ID of the voice agent'),
     ...
 ):
     ...
     try:
+        # Verify agent exists first
+        agent = await voice_agent_service.get_agent(agent_id)
+        if not agent:
+            return JSONResponse(
+                status_code=status.HTTP_404_NOT_FOUND,
+                content=response_formatter.buildErrorResponse(
+                    f'Voice agent not found with id: {agent_id}'
+                ),
+            )
+        
+        if not agent.get('welcome_message'):
+            return JSONResponse(
+                status_code=status.HTTP_404_NOT_FOUND,
+                content=response_formatter.buildErrorResponse(
+                    'Voice agent has no welcome message configured'
+                ),
+            )
+
         url = await voice_agent_service.get_welcome_message_audio_url(agent_id)

376-382: HTTP 500 may not be the correct status code for missing telephony config.

If the telephony config is not found, this indicates a data integrity issue (the agent references a non-existent or deleted config). Returning HTTP 500 suggests a server error, but this could also be considered a bad request if the agent's configuration is incomplete. Consider using HTTP 400 or 422 with a clearer message.

wavefront/server/modules/voice_agents_module/voice_agents_module/services/voice_agent_service.py (3)

189-202: Inbound number uniqueness check has O(n*m) complexity.

For each inbound number being validated, the code queries all non-deleted agents (line 191). If validating multiple numbers, this results in n * m database/memory operations where n = number of inbound numbers and m = number of agents.

Consider restructuring to query all agents once and check all numbers against the result, or add a database index/constraint for inbound number uniqueness.

♻️ Proposed optimization
+        # Query all agents once for efficiency
+        all_agents = await self.voice_agent_repository.find(is_deleted=False)
+        
         # Validate inbound number uniqueness
         for number in inbound_numbers:
-            # Query all agents and check if number is already assigned
-            all_agents = await self.voice_agent_repository.find(is_deleted=False)
             for agent in all_agents:
                 # Skip self when updating
                 if agent_id and agent.id == agent_id:

841-852: get_agent_by_inbound_number queries all agents on cache miss.

On cache miss, this method fetches all non-deleted agents and iterates through them (lines 843-852). This approach doesn't scale well with a large number of agents.

Consider adding a dedicated database query that filters by inbound number using a JSONB operator (e.g., @> in PostgreSQL) or maintaining a separate lookup table for inbound numbers.


607-634: Multiple conditions for audio regeneration could be consolidated.

The series of if statements checking for audio regeneration (lines 607-634) are repetitive. Consider using a helper or consolidating the checks.

♻️ Suggested consolidation
# Define fields that trigger audio regeneration
audio_regen_fields = {
    'welcome_message': existing_agent.welcome_message,
    'supported_languages': existing_dict.get('supported_languages'),
    'default_language': existing_dict.get('default_language'),
    'tts_voice_id': existing_agent.tts_voice_id,
    'tts_parameters': existing_dict.get('tts_parameters'),
    'tts_config_id': existing_dict.get('tts_config_id'),
}

audio_regeneration_needed = any(
    key in update_data and update_data[key] != old_value
    for key, old_value in audio_regen_fields.items()
)
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 42c9543 and 27e281b.

📒 Files selected for processing (45)
  • wavefront/client/src/constants/languages.ts
  • wavefront/client/src/pages/apps/[appId]/voice-agents/CreateVoiceAgentDialog.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/EditVoiceAgentDialog.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/OutboundCallDialog.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/index.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/CreateSttConfigDialog.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/EditSttConfigDialog.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/index.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/CreateTelephonyConfigDialog.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/EditTelephonyConfigDialog.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/index.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/CreateTtsConfigDialog.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/EditTtsConfigDialog.tsx
  • wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/index.tsx
  • wavefront/client/src/types/stt-config.ts
  • wavefront/client/src/types/telephony-config.ts
  • wavefront/client/src/types/tts-config.ts
  • wavefront/client/src/types/voice-agent.ts
  • wavefront/server/apps/call_processing/call_processing/constants/language_config.py
  • wavefront/server/apps/call_processing/call_processing/controllers/cache_controller.py
  • wavefront/server/apps/call_processing/call_processing/controllers/webhook_controller.py
  • wavefront/server/apps/call_processing/call_processing/services/floware_http_client.py
  • wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py
  • wavefront/server/apps/call_processing/call_processing/services/voice_agent_cache_service.py
  • wavefront/server/modules/db_repo_module/db_repo_module/alembic/versions/2026_01_08_1547-6010e49da528_add_inbound_voice_agent_support.py
  • wavefront/server/modules/db_repo_module/db_repo_module/models/stt_config.py
  • wavefront/server/modules/db_repo_module/db_repo_module/models/telephony_config.py
  • wavefront/server/modules/db_repo_module/db_repo_module/models/tts_config.py
  • wavefront/server/modules/db_repo_module/db_repo_module/models/voice_agent.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/stt_config_controller.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/telephony_config_controller.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/tts_config_controller.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/voice_agent_controller.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/models/stt_schemas.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/models/telephony_schemas.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/models/tts_schemas.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/models/voice_agent_schemas.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/services/stt_config_service.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/services/telephony_config_service.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/services/tts_config_service.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/services/voice_agent_service.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/utils/cache_invalidation.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/utils/cache_utils.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/utils/language_validation.py
  • wavefront/server/modules/voice_agents_module/voice_agents_module/utils/phone_validation.py
💤 Files with no reviewable changes (7)
  • wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/CreateTelephonyConfigDialog.tsx
  • wavefront/server/modules/voice_agents_module/voice_agents_module/services/stt_config_service.py
  • wavefront/client/src/types/telephony-config.ts
  • wavefront/client/src/types/stt-config.ts
  • wavefront/client/src/types/tts-config.ts
  • wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/EditTelephonyConfigDialog.tsx
  • wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/telephony_config_controller.py
🧰 Additional context used
🧬 Code graph analysis (11)
wavefront/client/src/pages/apps/[appId]/voice-agents/CreateVoiceAgentDialog.tsx (3)
wavefront/client/src/config/voice-providers.ts (2)
  • initializeParameters (260-270)
  • getProviderConfig (246-248)
wavefront/client/src/utils/parameter-helpers.ts (4)
  • getBooleanParameterWithDefault (49-57)
  • getNumberParameterWithDefault (34-44)
  • getNumberOrStringParameter (25-29)
  • getStringParameter (17-20)
wavefront/client/src/constants/languages.ts (2)
  • SUPPORTED_LANGUAGES (12-54)
  • getLanguageDisplayName (61-65)
wavefront/client/src/pages/apps/[appId]/voice-agents/index.tsx (1)
wavefront/client/src/constants/languages.ts (1)
  • getLanguageName (56-59)
wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/EditSttConfigDialog.tsx (2)
wavefront/client/src/components/ui/input.tsx (1)
  • Input (22-22)
wavefront/client/src/components/ui/select.tsx (1)
  • Select (133-133)
wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/EditTtsConfigDialog.tsx (2)
wavefront/client/src/components/ui/input.tsx (1)
  • Input (22-22)
wavefront/client/src/components/ui/select.tsx (1)
  • Select (133-133)
wavefront/server/apps/call_processing/call_processing/services/floware_http_client.py (2)
wavefront/server/apps/call_processing/call_processing/services/voice_agent_cache_service.py (2)
  • get_agent_by_inbound_number (266-349)
  • get_welcome_message_audio_url (351-398)
wavefront/server/modules/api_services_module/api_services_module/models/service.py (1)
  • error (131-143)
wavefront/client/src/pages/apps/[appId]/voice-agents/OutboundCallDialog.tsx (1)
wavefront/client/src/store/notification-store.ts (1)
  • useNotifyStore (32-32)
wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/CreateTtsConfigDialog.tsx (1)
wavefront/client/src/components/ui/input.tsx (1)
  • Input (22-22)
wavefront/server/apps/call_processing/call_processing/services/voice_agent_cache_service.py (2)
wavefront/server/apps/call_processing/call_processing/services/floware_http_client.py (3)
  • get_agent_by_inbound_number (127-171)
  • fetch_voice_agent (43-80)
  • get_welcome_message_audio_url (173-216)
wavefront/server/modules/voice_agents_module/voice_agents_module/utils/cache_utils.py (1)
  • get_voice_agent_cache_key (34-36)
wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/CreateSttConfigDialog.tsx (3)
wavefront/client/src/components/ui/input.tsx (1)
  • Input (22-22)
wavefront/client/src/components/ui/alert.tsx (2)
  • Alert (44-44)
  • AlertDescription (44-44)
wavefront/client/src/components/ui/dialog.tsx (1)
  • DialogFooter (115-115)
wavefront/server/modules/voice_agents_module/voice_agents_module/services/voice_agent_service.py (6)
wavefront/server/modules/voice_agents_module/voice_agents_module/utils/language_validation.py (3)
  • validate_languages_for_configs (228-282)
  • validate_default_language (285-303)
  • format_language_prompt (319-337)
wavefront/server/modules/voice_agents_module/voice_agents_module/utils/phone_validation.py (1)
  • validate_phone_numbers (32-67)
wavefront/server/modules/voice_agents_module/voice_agents_module/services/tts_config_service.py (1)
  • get_config (86-118)
wavefront/server/modules/voice_agents_module/voice_agents_module/services/telephony_config_service.py (1)
  • get_config (98-132)
wavefront/server/modules/voice_agents_module/voice_agents_module/services/stt_config_service.py (1)
  • get_config (86-118)
wavefront/server/modules/voice_agents_module/voice_agents_module/utils/cache_invalidation.py (1)
  • invalidate_call_processing_cache (9-80)
wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/voice_agent_controller.py (3)
wavefront/server/modules/voice_agents_module/voice_agents_module/services/telephony_config_service.py (1)
  • get_config (98-132)
wavefront/server/modules/voice_agents_module/voice_agents_module/services/voice_agent_service.py (2)
  • get_agent_by_inbound_number (823-854)
  • get_welcome_message_audio_url (734-777)
wavefront/server/modules/api_services_module/api_services_module/models/service.py (1)
  • error (131-143)
🪛 Ruff (0.14.10)
wavefront/server/apps/call_processing/call_processing/services/floware_http_client.py

156-156: Consider moving this statement to an else block

(TRY300)

wavefront/server/modules/voice_agents_module/voice_agents_module/utils/language_validation.py

201-201: Avoid specifying long messages outside the exception class

(TRY003)


225-225: Avoid specifying long messages outside the exception class

(TRY003)

wavefront/server/apps/call_processing/call_processing/services/voice_agent_cache_service.py

312-312: Do not catch blind exception: Exception

(BLE001)


344-344: Do not catch blind exception: Exception

(BLE001)


393-393: Do not catch blind exception: Exception

(BLE001)

wavefront/server/apps/call_processing/call_processing/controllers/cache_controller.py

108-108: Consider [*list(VALID_CONFIG_TYPES), 'inbound_number'] instead of concatenation

Replace with [*list(VALID_CONFIG_TYPES), 'inbound_number']

(RUF005)


144-147: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

wavefront/server/modules/db_repo_module/db_repo_module/alembic/versions/2026_01_08_1547-6010e49da528_add_inbound_voice_agent_support.py

116-119: Possible SQL injection vector through string-based query construction

(S608)

wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py

322-322: Unused function argument: processor

(ARG001)


394-394: Do not catch blind exception: Exception

(BLE001)


428-428: Consider [updated_system_message, *current_messages[1:]] instead of concatenation

Replace with [updated_system_message, *current_messages[1:]]

(RUF005)

wavefront/server/apps/call_processing/call_processing/controllers/webhook_controller.py

42-44: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


82-82: Do not catch blind exception: Exception

(BLE001)

wavefront/server/modules/voice_agents_module/voice_agents_module/services/voice_agent_service.py

258-258: Avoid specifying long messages outside the exception class

(TRY003)

wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/voice_agent_controller.py

443-445: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


446-448: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


481-481: Do not perform function call Path in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


482-484: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


485-487: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


509-509: Do not catch blind exception: Exception

(BLE001)


510-510: Use explicit conversion flag

Replace with conversion flag

(RUF010)


514-514: Use explicit conversion flag

Replace with conversion flag

(RUF010)

🔇 Additional comments (55)
wavefront/server/modules/db_repo_module/db_repo_module/models/stt_config.py (1)

5-5: Import cleanup is correct with no broken references to removed fields.

The removal of Text (and json) aligns with the removal of the language and parameters fields. The remaining imports (String, func) are properly used. No code in the repository references the removed SttConfig.language or SttConfig.parameters fields, confirming the refactoring was completed consistently across the codebase.

wavefront/server/modules/db_repo_module/db_repo_module/models/tts_config.py (1)

1-47: LGTM!

The model simplification is clean and aligns with the broader refactor moving language and voice configuration to the voice agent level. The to_dict method correctly handles serialization and properly excludes the api_key by default for security.

wavefront/server/modules/voice_agents_module/voice_agents_module/models/tts_schemas.py (1)

1-49: LGTM!

The schema changes are consistent with the model refactor. The UNSET sentinel pattern for partial updates is appropriate, and the response schema correctly excludes sensitive api_key data.

wavefront/server/modules/voice_agents_module/voice_agents_module/utils/cache_invalidation.py (1)

9-43: LGTM!

The type expansion to accept UUID | str is well implemented. The conversion logic correctly handles both types, and the change is backward compatible with existing UUID-based callers while enabling phone number identifiers for the new inbound_number config type.

wavefront/server/apps/call_processing/call_processing/constants/language_config.py (1)

1-100: Well-structured language configuration.

Good inclusion of native script keywords (e.g., 'हिंदी' for Hindi, '中文' for Chinese) alongside romanized forms—this improves detection accuracy when users specify their preferred language. The dual-language instructions (English + native) are a nice touch for clarity.

wavefront/server/modules/voice_agents_module/voice_agents_module/services/telephony_config_service.py (1)

38-96: LGTM!

The removal of phone_numbers from create_config aligns with the architectural change moving phone number management to voice agent records. The method signature and repository call are clean, and all callers have been updated accordingly.

wavefront/server/modules/db_repo_module/db_repo_module/models/voice_agent.py (1)

37-51: New voice agent fields look well-structured.

The new TTS/STT configuration fields and multi-language support are properly defined with appropriate JSONB types and sensible defaults. Using default=lambda: ['en'] correctly avoids the mutable default argument pitfall.

wavefront/server/modules/voice_agents_module/voice_agents_module/utils/language_validation.py (2)

228-282: Validation logic handles edge cases appropriately.

The approach of returning empty sets for unimplemented providers and treating all languages as valid in that case is a pragmatic choice that won't block functionality while still validating for known providers.


319-337: Well-implemented Oxford comma formatting.

The format_language_prompt function correctly handles single, double, and multiple language cases with proper Oxford comma style.

wavefront/server/modules/db_repo_module/db_repo_module/alembic/versions/2026_01_08_1547-6010e49da528_add_inbound_voice_agent_support.py (1)

23-49: Schema changes and default initialization look correct.

The idempotent ADD COLUMN IF NOT EXISTS approach and the COALESCE-based default initialization handle re-runs gracefully.

wavefront/server/modules/voice_agents_module/voice_agents_module/utils/cache_utils.py (1)

49-51: The concern about varying phone number formats is not applicable here. Phone numbers are validated to E.164 format (+[country code][number]) before reaching this function, as confirmed by the validate_phone_numbers function that enforces strict E.164 compliance. This standardized format eliminates the risk of cache misses due to format variations.

However, note that this newly added function is not currently being imported or used anywhere in the codebase. The cache key pattern f'inbound_number:{phone_number}' is hardcoded in multiple locations (voice_agent_service.py, voice_agent_cache_service.py, cache_controller.py) instead of using this function. Consider using this utility function in those places to maintain consistency and reduce duplication.

Likely an incorrect or invalid review comment.

wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/index.tsx (1)

78-85: LGTM!

The filter logic correctly aligns with the simplified table columns. Search now covers the three relevant displayed fields: display name, description, and provider.

wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/index.tsx (1)

78-85: LGTM!

The filter logic is consistent with the TTS configs page and correctly removes language from search criteria to match the simplified table schema.

wavefront/client/src/pages/apps/[appId]/voice-agents/index.tsx (3)

12-12: LGTM!

Import correctly added to support language name display in the tooltip.


137-139: LGTM!

New table headers appropriately reflect the expanded voice agent data model with phone numbers and language support.


150-155: LGTM!

Inbound and outbound number counts correctly use optional chaining with a 0 fallback, providing accurate display when numbers aren't configured.

wavefront/server/modules/db_repo_module/db_repo_module/models/telephony_config.py (1)

49-56: LGTM!

The to_dict method correctly updates JSON field parsing to exclude the removed phone_numbers field, maintaining consistency with the schema migration.

wavefront/client/src/pages/apps/[appId]/voice-agents/OutboundCallDialog.tsx (2)

24-28: LGTM!

Props interface correctly simplified by removing the now-unnecessary appId prop, aligning with the refactored data flow.


30-37: LGTM!

Clean refactoring that sources phone numbers directly from the voice agent rather than fetching from telephony config. This simplifies the component and reduces unnecessary data dependencies. The empty array fallback properly handles undefined/null cases.

wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/tts_config_controller.py (1)

146-161: LGTM!

The update logic correctly uses the UNSET sentinel pattern for partial updates, only including fields that were explicitly provided in the payload. The early return with a 400 error when no fields are provided is appropriate.

wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/EditSttConfigDialog.tsx (3)

63-73: LGTM!

The useEffect correctly resets the form when the dialog opens or when the config prop changes, ensuring the form always reflects the current config state.


135-152: Good UX improvement.

Disabling the provider field and adding an explanatory description is a clear way to communicate that the provider cannot be changed after creation.


183-197: LGTM!

The security note alert provides helpful guidance about API key handling. The placement within the FormItem for api_key is appropriate.

wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/CreateTtsConfigDialog.tsx (4)

32-37: LGTM!

The schema correctly defines the simplified TTS config fields with appropriate validation. The provider enum matches the expected TTS providers.


61-71: LGTM!

The form reset on dialog close ensures a clean state for the next creation attempt.


73-91: LGTM!

The submit handler correctly sends the simplified payload with proper trimming of string values. Error handling is appropriate.


172-186: LGTM!

The API key field is correctly marked as required for creation (unlike edit where it's optional). The password input type appropriately masks the key.

wavefront/server/modules/voice_agents_module/voice_agents_module/models/stt_schemas.py (3)

35-38: LGTM!

The UpdateSttConfigPayload correctly uses the UNSET sentinel pattern for partial updates. The Union[str, Any] typing allows for distinguishing between "field not provided" (UNSET) and "field explicitly set to None".


41-48: LGTM!

The SttConfigResponse model is appropriately simplified, removing the language and parameters fields that are now managed at the voice agent level.


11-16: Hardcoded Zod schema creates maintenance risk: Update to derive provider validation from VOICE_PROVIDERS_CONFIG.

The client limits STT providers to ['deepgram'] via hardcoded Zod schema, while the dialog renders providers dynamically from VOICE_PROVIDERS_CONFIG.stt.providers. This disconnect means if VOICE_PROVIDERS_CONFIG is updated with new providers, the Zod validation in CreateSttConfigDialog.tsx (line 32) and EditSttConfigDialog.tsx (line 26) will silently reject them.

Additionally, the server's SttProvider enum defines 5 providers (deepgram, assemblyai, whisper, google, azure) but the client only exposes deepgram. This mismatch suggests these other providers aren't yet implemented in pipecat. Either the server enum should document this limitation, or the Zod schema should derive its allowed values from VOICE_PROVIDERS_CONFIG.stt.providers to avoid future sync issues.

wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/CreateSttConfigDialog.tsx (3)

61-71: LGTM!

Form reset on dialog close is correctly implemented.


188-192: LGTM!

The security alert provides appropriate guidance about API key handling.


198-200: LGTM!

The submit button correctly shows loading state and disables during submission to prevent double-clicks.

wavefront/server/modules/voice_agents_module/voice_agents_module/utils/phone_validation.py (3)

6-9: LGTM! E.164 regex pattern is correct.

The regex ^\+[1-9]\d{1,14}$ correctly validates E.164 format: starts with +, followed by a digit 1-9 (country codes cannot start with 0), then 1-14 additional digits for a total of up to 15 digits.


12-29: LGTM!

Clean implementation with thorough docstring and examples.


32-67: LGTM!

Well-structured validation with clear error messages that include the offending values and expected format examples. The tuple return pattern (is_valid, error_message) is clean.

wavefront/server/modules/voice_agents_module/voice_agents_module/models/telephony_schemas.py (1)

1-5: LGTM! Schema cleanup aligns with PR objectives.

Removing phone_numbers from telephony schemas is consistent with the architectural change to manage phone numbers at the voice agent level instead of telephony configs.

wavefront/server/apps/call_processing/call_processing/controllers/cache_controller.py (2)

30-30: LGTM! Good documentation of the type change.

The comment clearly explains the dual-purpose nature of config_id (UUID string for standard configs, phone number for inbound_number type).


118-136: LGTM! Clean separation for inbound_number handling.

The early return for inbound_number type correctly bypasses UUID validation and Floware refresh since inbound number mappings don't need to be re-fetched from the API.

wavefront/server/apps/call_processing/call_processing/services/floware_http_client.py (1)

173-216: LGTM! Robust response handling.

The method correctly handles multiple response formats (wrapped/unwrapped, dict/string) and gracefully returns empty string on 404. This defensive approach is appropriate for optional resources like welcome audio.

wavefront/client/src/constants/languages.ts (3)

56-65: LGTM! Clean utility functions with graceful fallbacks.

The functions handle unknown codes gracefully by returning the input code, preventing UI errors when encountering unexpected language codes.


12-54: LGTM! Comprehensive language support.

Good coverage of major world languages with native names for accessibility. The list includes both widely-spoken languages and regional Indian languages, aligning well with multi-language voice agent requirements.


1-4: Add missing languages to match backend support or clarify the language scope.

The frontend SUPPORTED_LANGUAGES list is missing two languages that the backend supports: ka (Georgian) and tl (Tagalog). The current comment claims the list "Matches backend language validation," but the backend's LANGUAGE_NAMES dictionary in language_validation.py contains 43 languages while the frontend only exposes 41. Either add these languages to the frontend list for full parity with backend capabilities, or update the comment to accurately reflect that the frontend list is a subset of backend-supported languages.

wavefront/server/modules/voice_agents_module/voice_agents_module/models/voice_agent_schemas.py (2)

93-100: LGTM!

The response schema correctly defines non-optional types for list fields (inbound_numbers, outbound_numbers, supported_languages) and default_language, ensuring consistent API responses even when the underlying data is empty.


52-59: Validation already exists in the service layer.

The constraint that default_language must be in supported_languages is already validated via validate_default_language() in the service layer (voice_agent_service.py, line 205-209). However, adding a Pydantic model_validator at the schema level would still be beneficial for earlier validation and stricter API contract enforcement, as it would catch violations before they reach the service layer.

wavefront/server/apps/call_processing/call_processing/services/voice_agent_cache_service.py (3)

312-315: Broad exception handling is acceptable for cache resilience.

The except Exception catch here is intentional for fault tolerance - a failure to fetch the agent from API shouldn't crash the inbound lookup flow. The error is logged with context, and the code falls through to the cache-miss path. This pattern aligns with the service's fault-tolerant design.


266-283: LGTM on the caching strategy.

The two-level caching approach (inbound number → agent ID mapping, plus full agent data cache) is efficient and well-documented. The docstring clearly explains the cache-first strategy with API fallback.


331-336: No action needed. The cache_manager.add() method uses nx=False by default, which means it will overwrite existing values in Redis (not skip them if the key exists). If an inbound number's agent assignment changes, the mapping will be updated immediately on the next call, not persist as stale until TTL expires. The method name is somewhat misleading, but the current implementation correctly handles cache updates.

Likely an incorrect or invalid review comment.

wavefront/server/modules/voice_agents_module/voice_agents_module/controllers/stt_config_controller.py (2)

43-48: LGTM on the simplified create flow.

The controller now correctly delegates only credential-related fields (display_name, description, provider, api_key) to the service, aligning with the PR's objective to move language/parameters to the voice agent level.


146-161: Clean partial update implementation.

The update logic correctly excludes provider from updatable fields (making it immutable after creation) and only includes fields that are explicitly set. This aligns with the frontend behavior where the provider field is disabled in the edit dialog.

wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/EditTtsConfigDialog.tsx (2)

75-97: LGTM on the submit handler.

The update payload correctly excludes provider (since it's immutable) and conditionally includes api_key only when provided, preserving the existing key if left empty. This is clean and user-friendly.


127-156: Good UX for immutable provider field.

The disabled provider select with clear explanation ("Provider cannot be changed after creation") provides good user feedback. This is consistent with the backend behavior where provider updates are not accepted.

wavefront/client/src/types/voice-agent.ts (2)

16-24: LGTM on the VoiceAgent interface extensions.

The new fields are well-typed and consistent with the server-side VoiceAgentResponse schema:

  • Non-optional arrays for inbound_numbers, outbound_numbers, supported_languages
  • Non-optional default_language and tts_voice_id
  • Nullable parameter objects for tts_parameters and stt_parameters

42-50: Request payloads align with server schemas.

The tts_voice_id is correctly required in CreateVoiceAgentRequest while language and phone number fields are optional, matching the server-side CreateVoiceAgentPayload where tts_voice_id is a required field and others have defaults or are optional.

wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py (1)

344-357: Keyword-based language detection may produce false positives.

The language detection relies on matching keywords from LANGUAGE_KEYWORDS against user messages. Common words could trigger incorrect detections (e.g., "yes" appearing in multiple languages, or loan words). Consider adding a confidence threshold or using the LLM for language detection in ambiguous cases.

Comment on lines +156 to +163
<TableCell>
<span
className="text-sm text-gray-600"
title={agent.supported_languages?.map(getLanguageName).join(', ')}
>
{agent.supported_languages?.length || 1} ({agent.default_language || 'en'})
</span>
</TableCell>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Misleading fallback value for language count.

The fallback || 1 on line 161 displays "1" when supported_languages is undefined or empty, which may mislead users into thinking a language is configured when none actually is. Consider using || 0 or displaying a dash for consistency with other empty states.

Suggested fix
                     <TableCell>
                       <span
                         className="text-sm text-gray-600"
                         title={agent.supported_languages?.map(getLanguageName).join(', ')}
                       >
-                        {agent.supported_languages?.length || 1} ({agent.default_language || 'en'})
+                        {agent.supported_languages?.length || 0} ({agent.default_language || 'en'})
                       </span>
                     </TableCell>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<TableCell>
<span
className="text-sm text-gray-600"
title={agent.supported_languages?.map(getLanguageName).join(', ')}
>
{agent.supported_languages?.length || 1} ({agent.default_language || 'en'})
</span>
</TableCell>
<TableCell>
<span
className="text-sm text-gray-600"
title={agent.supported_languages?.map(getLanguageName).join(', ')}
>
{agent.supported_languages?.length || 0} ({agent.default_language || 'en'})
</span>
</TableCell>
🤖 Prompt for AI Agents
In @wavefront/client/src/pages/apps/[appId]/voice-agents/index.tsx around lines
156 - 163, The count fallback currently uses agent.supported_languages?.length
|| 1 which incorrectly shows "1" when supported_languages is undefined or empty;
update the span to show a truthful empty state by using
agent.supported_languages?.length ?? 0 (or render a dash '-') and keep the title
safe by guarding the join (e.g.,
title={agent.supported_languages?.map(getLanguageName).join(', ') || '-'}) so
the TableCell/span displays 0 or '-' when no languages exist and still shows the
default_language (agent.default_language || 'en') as before.

Comment on lines +33 to +34
'fil': ['filipino', 'pilipino', 'tagalog'],
'tl': ['tagalog', 'filipino'],
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential ambiguity between fil and tl language codes.

Both fil (Filipino) and tl (Tagalog) share overlapping keywords ('tagalog', 'filipino'), which could cause non-deterministic behavior in language detection. When a user mentions "tagalog" or "filipino", the detected language depends on dictionary iteration order rather than explicit logic.

Consider either:

  1. Consolidating to a single code (e.g., keep only fil as the modern ISO 639-1 code for Filipino/Tagalog)
  2. Differentiating keywords so each code has unique detection triggers
🤖 Prompt for AI Agents
In
@wavefront/server/apps/call_processing/call_processing/constants/language_config.py
around lines 33 - 34, The language alias mapping contains overlapping entries
for 'fil' and 'tl' (both include 'tagalog'/'filipino'), causing
non-deterministic detection; update the language aliases dict (the mapping that
defines 'fil' and 'tl') to remove the ambiguity by either consolidating into a
single canonical code (e.g., keep only 'fil' and drop the 'tl' key) or by making
their keyword lists mutually exclusive (give each key unique trigger words), and
update any related comments/tests that reference 'fil' or 'tl' to reflect the
new canonical choice.

Comment on lines +152 to +178
def downgrade() -> None:
# Restore phone_numbers column to telephony_configs table
op.add_column(
'telephony_configs', sa.Column('phone_numbers', sa.Text(), nullable=True)
)

# Restore TTS/STT config columns
op.add_column(
'tts_configs', sa.Column('voice_id', sa.String(length=255), nullable=True)
)
op.add_column(
'tts_configs', sa.Column('language', sa.String(length=64), nullable=True)
)
op.add_column('tts_configs', sa.Column('parameters', sa.Text(), nullable=True))
op.add_column(
'stt_configs', sa.Column('language', sa.String(length=64), nullable=True)
)
op.add_column('stt_configs', sa.Column('parameters', sa.Text(), nullable=True))

# Drop columns from voice_agents
op.drop_column('voice_agents', 'default_language')
op.drop_column('voice_agents', 'supported_languages')
op.drop_column('voice_agents', 'outbound_numbers')
op.drop_column('voice_agents', 'inbound_numbers')
op.drop_column('voice_agents', 'stt_parameters')
op.drop_column('voice_agents', 'tts_parameters')
op.drop_column('voice_agents', 'tts_voice_id')
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Downgrade does not restore migrated data.

The upgrade migrates voice_id, parameters from tts_configs and stt_configs into voice_agents, then drops those columns. The downgrade restores the column structure but not the data. If a rollback is needed, this data will be lost.

Consider adding a reverse data migration or documenting this as a one-way migration.

🤖 Prompt for AI Agents
In
@wavefront/server/modules/db_repo_module/db_repo_module/alembic/versions/2026_01_08_1547-6010e49da528_add_inbound_voice_agent_support.py
around lines 152 - 178, The downgrade currently restores columns but fails to
repopulate them from the new voice_agents table, causing data loss; update
downgrade() to migrate data back before dropping voice_agents columns by: after
adding back columns (tts_configs.voice_id, tts_configs.parameters,
stt_configs.language, stt_configs.parameters, telephony_configs.phone_numbers)
run SQL updates (via op.execute) that join voice_agents to
tts_configs/stt_configs/telephony_configs and set the restored columns from
voice_agents.tts_voice_id, voice_agents.tts_parameters,
voice_agents.stt_parameters, voice_agents.default_language (and
supported_languages/outbound_numbers/inbound_numbers as appropriate), then only
drop the columns from voice_agents; alternatively document this as irreversible
if you decide not to implement the reverse migration.

Comment on lines +52 to +171
# Provider language support (extracted from pipecat language mappings)
ELEVENLABS_LANGUAGES: Set[str] = {
'ar',
'bg',
'cs',
'da',
'de',
'el',
'en',
'es',
'fi',
'fil',
'fr',
'hi',
'hr',
'hu',
'id',
'it',
'ja',
'ko',
'ms',
'nl',
'no',
'pl',
'pt',
'ro',
'ru',
'sk',
'sv',
'ta',
'tr',
'uk',
'vi',
'zh',
}

CARTESIA_LANGUAGES: Set[str] = {
'ar',
'bg',
'bn',
'cs',
'da',
'de',
'en',
'el',
'es',
'fi',
'fr',
'gu',
'he',
'hi',
'hr',
'hu',
'id',
'it',
'ja',
'ka',
'kn',
'ko',
'ml',
'mr',
'ms',
'nl',
'no',
'pa',
'pl',
'pt',
'ro',
'ru',
'sk',
'sv',
'ta',
'te',
'th',
'tl',
'tr',
'uk',
'vi',
'zh',
}

# Deepgram STT supports 40+ languages
DEEPGRAM_STT_LANGUAGES: Set[str] = {
'ar',
'bg',
'ca',
'cs',
'da',
'de',
'el',
'en',
'es',
'et',
'fi',
'fr',
'hi',
'hu',
'id',
'it',
'ja',
'ko',
'lt',
'lv',
'ms',
'nl',
'no',
'pl',
'pt',
'ro',
'ru',
'sk',
'sv',
'ta',
'te',
'th',
'tr',
'uk',
'vi',
'zh',
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

ElevenLabs TTS supported languages 2025 official documentation

💡 Result:

As of the official ElevenLabs documentation (checked Jan 12, 2026):

  • Eleven v3: supports 74 languages. [1]
  • Multilingual v2: supports 29 languages. [1][2]
  • Flash v2.5 / Turbo v2.5: supports 32 languages (Flash v2.5 specifically listed as 32). [1][2]

For the full per-language lists, see ElevenLabs' support & docs pages. [1][2]

Sources:
[1] ElevenLabs Help — "What languages do you support?".
[2] ElevenLabs Documentation — "Text to Speech / Supported languages".


🌐 Web query:

Cartesia text-to-speech supported languages 2025

💡 Result:

As of 2025 Cartesia’s Sonic TTS lineup (Sonic-3 / Sonic series) supports the following languages:

English (en), French (fr), German (de), Spanish (es), Portuguese (pt), Chinese (zh), Japanese (ja), Hindi (hi), Italian (it), Korean (ko), Dutch (nl), Polish (pl), Russian (ru), Swedish (sv), Turkish (tr), Tagalog (tl), Bulgarian (bg), Romanian (ro), Arabic (ar), Czech (cs), Greek (el), Finnish (fi), Croatian (hr), Malay (ms), Slovak (sk), Danish (da), Tamil (ta), Ukrainian (uk), Hungarian (hu), Norwegian (no), Vietnamese (vi), Bengali (bn), Thai (th), Hebrew (he), Georgian (ka), Indonesian (id), Telugu (te), Gujarati (gu), Kannada (kn), Malayalam (ml), Marathi (mr), Punjabi (pa).

Sources: Cartesia TTS / Sonic docs (language support lists). [1][2]

References
[1] Cartesia Sonic-3 language support documentation. (docs.cartesia.ai)
[2] Cartesia TTS / Sonic model pages (Sonic / Sonic-2 / sonic-turbo). (docs.cartesia.ai)

Citations:


🌐 Web query:

Deepgram STT supported languages 2025 official documentation

💡 Result:

The official 2025 Deepgram Speech-to-Text supported languages are listed in Deepgram's documentation:

  • Models & Languages Overview (full per-model language list). [1]
  • Language Detection supported languages (detection-specific list). [2]

If you want, I can extract and paste the full language list from the Models & Languages page here.

Sources:
[1] Deepgram — Models & Languages Overview. [developers.deepgram.com/docs/models-languages-overview]
[2] Deepgram — Language Detection (supported languages). [developers.deepgram.com/docs/language-detection]


🏁 Script executed:

# Count the languages in each provider set from the code
cat > /tmp/count_languages.py << 'EOF'
elevenlabs = {
    'ar', 'bg', 'cs', 'da', 'de', 'el', 'en', 'es', 'fi', 'fil',
    'fr', 'hi', 'hr', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'nl',
    'no', 'pl', 'pt', 'ro', 'ru', 'sk', 'sv', 'ta', 'tr', 'uk',
    'vi', 'zh'
}

cartesia = {
    'ar', 'bg', 'bn', 'cs', 'da', 'de', 'en', 'el', 'es', 'fi',
    'fr', 'gu', 'he', 'hi', 'hr', 'hu', 'id', 'it', 'ja', 'ka',
    'kn', 'ko', 'ml', 'mr', 'ms', 'nl', 'no', 'pa', 'pl', 'pt',
    'ro', 'ru', 'sk', 'sv', 'ta', 'te', 'th', 'tl', 'tr', 'uk',
    'vi', 'zh'
}

deepgram = {
    'ar', 'bg', 'ca', 'cs', 'da', 'de', 'el', 'en', 'es', 'et',
    'fi', 'fr', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'lt', 'lv',
    'ms', 'nl', 'no', 'pl', 'pt', 'ro', 'ru', 'sk', 'sv', 'ta',
    'te', 'th', 'tr', 'uk', 'vi', 'zh'
}

print(f"ElevenLabs: {len(elevenlabs)} languages")
print(f"Cartesia: {len(cartesia)} languages")
print(f"Deepgram: {len(deepgram)} languages")

# Also show which languages are in code
print("\nElevenLabs languages:", sorted(elevenlabs))
print("\nCartesia languages:", sorted(cartesia))
print("\nDeepgram languages:", sorted(deepgram))
EOF
python /tmp/count_languages.py

Repository: rootflo/wavefront

Length of output: 147


🌐 Web query:

ElevenLabs supported languages complete list 2025 multilingual v2 model

💡 Result:

ElevenLabs Multilingual v2 — supported languages (29 total, per ElevenLabs docs, January 2026):

  1. Arabic (ARA)
  2. Bulgarian (BUL)
  3. Chinese / Mandarin (CMN)
  4. Croatian (HRV)
  5. Czech (CES)
  6. Danish (DAN)
  7. Dutch (NLD)
  8. English (ENG: USA, UK, Australia, Canada)
  9. Filipino (FIL)
  10. Finnish (FIN)
  11. French (FRA: France, Canada)
  12. German (DEU)
  13. Greek (ELL)
  14. Hindi (HIN)
  15. Indonesian (IND)
  16. Italian (ITA)
  17. Japanese (JPN)
  18. Korean (KOR)
  19. Malay (MSA)
  20. Polish (POL)
  21. Portuguese (POR: Brazil, Portugal)
  22. Romanian (RON)
  23. Russian (RUS)
  24. Slovak (SLK)
  25. Spanish (SPA: Spain, Mexico)
  26. Swedish (SWE)
  27. Tamil (TAM)
  28. Turkish (TUR)
  29. Ukrainian (UKR)

Sources: ElevenLabs model docs and Help Center. [1][2]

References
[1] ElevenLabs Models documentation — Multilingual v2 (supported languages).
[2] ElevenLabs Help Center — “What languages do you support?”


🌐 Web query:

Deepgram speech-to-text supported languages complete list 2025 nova model

💡 Result:

Do you mean Nova-2 or Nova-3? Quick answer below; I can expand with full language codes or a single combined list once you confirm which Nova you want.

  • Nova-2 (as announced / documented May 14, 2024) — 36 languages: Bulgarian; Catalan; Chinese (Mandarin, Simplified); Chinese (Mandarin, Traditional); Czech; Danish; Dutch; English; Estonian; Finnish; Flemish; French; German; German (Switzerland); Greek; Hindi; Hungarian; Indonesian; Italian; Japanese; Korean; Latvian; Lithuanian; Malay; Norwegian; Polish; Portuguese; Romanian; Russian; Slovak; Spanish; Swedish; Thai; Turkish; Ukrainian; Vietnamese. [1]

  • Nova-3 (highest‑performing Nova model; supports a multilingual "multi" option plus many per‑language models — documented with staged language rollouts through 2025). See the Models & Languages overview for Nova-3 supported languages and the changelog for recent additions. [2]

Sources:
[1] Deepgram announcement / changelog — "Nova-2 Now Supports 36 Languages" (May 14, 2024).
[2] Deepgram Developers — Models & Languages overview / Nova-3 docs and changelog (2025 updates).


🏁 Script executed:

# Search for ElevenLabs model references in the codebase
rg -i "eleven|multilingual|flash|v2|v3" --type py -A 2 -B 2 | head -100

Repository: rootflo/wavefront

Length of output: 10974


🏁 Script executed:

# Look for voice agent implementations that might specify the model
find . -type f -name "*.py" | xargs grep -l "elevenlabs\|ElevenLabs" | head -10

Repository: rootflo/wavefront

Length of output: 426


🏁 Script executed:

# Check the imports and usage in the language_validation file
head -60 wavefront/server/modules/voice_agents_module/voice_agents_module/utils/language_validation.py

Repository: rootflo/wavefront

Length of output: 1333


Remove unsupported languages from ELEVENLABS_LANGUAGES or verify against current ElevenLabs model.

The code uses eleven_multilingual_v2 model by default, which officially supports 29 languages per ElevenLabs documentation (Jan 2026). However, ELEVENLABS_LANGUAGES includes 32 languages with three unsupported additions: 'hi' (Hindi), 'no' (Norwegian), 'vi' (Vietnamese). This mismatch could allow users to configure languages that will fail at the API level.

CARTESIA_LANGUAGES and DEEPGRAM_STT_LANGUAGES appear accurate against current provider documentation.

🤖 Prompt for AI Agents
In
@wavefront/server/modules/voice_agents_module/voice_agents_module/utils/language_validation.py
around lines 52 - 171, ELEVENLABS_LANGUAGES contains entries that don't match
the eleven_multilingual_v2 model; update ELEVENLABS_LANGUAGES to exactly reflect
ElevenLabs' supported languages (remove 'hi', 'no', 'vi' or any other
unsupported codes) or add a verification step that checks the configured
language against the live ElevenLabs model before use; locate and edit the
ELEVENLABS_LANGUAGES constant in language_validation.py and ensure any caller
(e.g., functions that reference ELEVENLABS_LANGUAGES) fails fast with a clear
error if an unsupported language is requested.

@rootflo-hardik rootflo-hardik changed the title Voice Agent Refactoring and bug fixes Add inbound voice agent support with language detection and configuration Jan 13, 2026
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