/** * Ultravox Voice AI Service * Creates calls via Ultravox API and manages voice configuration */ // API Configuration const ULTRAVOX_API_URL = 'https://api.ultravox.ai/api'; const ULTRAVOX_API_KEY = '4miSVLym.HF3lV9y4euiuzcEbPPTLHEugrOu4jpNU'; // Available voices export interface UltravoxVoice { id: string; name: string; description: string; language: string; gender: 'female' | 'male'; flag: string; } export const ULTRAVOX_VOICES: UltravoxVoice[] = [ { id: 'Sarah', name: 'Sarah', description: 'Warm and friendly', language: 'English', gender: 'female', flag: 'πŸ‡ΊπŸ‡Έ', }, { id: 'Wendy', name: 'Wendy', description: 'Professional', language: 'English', gender: 'female', flag: 'πŸ‡ΊπŸ‡Έ', }, { id: 'Timothy', name: 'Timothy', description: 'Calm and clear', language: 'English', gender: 'male', flag: 'πŸ‡ΊπŸ‡Έ', }, { id: 'Larisa', name: 'Larisa', description: 'Russian voice', language: 'Russian', gender: 'female', flag: 'πŸ‡·πŸ‡Ί', }, ]; // Default voice export const DEFAULT_VOICE = ULTRAVOX_VOICES[0]; // Sarah // Tool definitions for function calling export interface UltravoxTool { temporaryTool: { modelToolName: string; description: string; dynamicParameters?: Array<{ name: string; location: string; schema: { type: string; description: string; }; required: boolean; }>; client?: Record; }; } export const ULTRAVOX_TOOLS: UltravoxTool[] = [ { temporaryTool: { modelToolName: 'navigateToBeneficiaries', description: 'Navigate to the beneficiaries list screen when user wants to see or manage their loved ones', client: {}, }, }, { temporaryTool: { modelToolName: 'navigateToChat', description: 'Navigate to the chat screen for text-based conversation', client: {}, }, }, { temporaryTool: { modelToolName: 'navigateToProfile', description: 'Navigate to the user profile settings screen', client: {}, }, }, { temporaryTool: { modelToolName: 'checkBeneficiaryStatus', description: 'Check the current wellness status of a specific beneficiary', dynamicParameters: [ { name: 'beneficiaryName', location: 'PARAMETER_LOCATION_BODY', schema: { type: 'string', description: 'The name of the beneficiary to check', }, required: true, }, ], client: {}, }, }, ]; // System prompt generator export function getSystemPrompt(beneficiaryName: string): string { return `You are Julia, a compassionate and knowledgeable AI wellness assistant for WellNuo app. Your role is to help caregivers monitor and understand the wellbeing of their loved ones. Current beneficiary: ${beneficiaryName} Guidelines: - Be warm, empathetic, and supportive in your responses - Provide clear, concise information about wellness metrics - Offer practical suggestions for improving wellbeing - If asked about specific health concerns, recommend consulting healthcare professionals - You can navigate the app using available tools when the user requests it - Keep responses conversational and natural for voice interaction - Speak in a calm, reassuring tone Remember: You're speaking with a caregiver who wants the best for their loved one. Be supportive and helpful while maintaining appropriate boundaries about medical advice.`; } // API Response types export interface CreateCallResponse { callId: string; joinUrl: string; created: string; ended?: string; model: string; voice: string; firstSpeaker: string; transcriptOptional: boolean; recordingEnabled: boolean; } export interface UltravoxError { error: string; message: string; } /** * Create a new Ultravox call */ export async function createCall(options: { systemPrompt: string; voice?: string; tools?: UltravoxTool[]; firstSpeaker?: 'FIRST_SPEAKER_AGENT' | 'FIRST_SPEAKER_USER'; }): Promise<{ success: true; data: CreateCallResponse } | { success: false; error: string }> { try { const response = await fetch(`${ULTRAVOX_API_URL}/calls`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': ULTRAVOX_API_KEY, }, body: JSON.stringify({ systemPrompt: options.systemPrompt, model: 'fixie-ai/ultravox', voice: options.voice || 'Sarah', firstSpeaker: options.firstSpeaker || 'FIRST_SPEAKER_AGENT', selectedTools: options.tools || ULTRAVOX_TOOLS, medium: { webRtc: {} }, recordingEnabled: false, maxDuration: '1800s', // 30 minutes max }), }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); console.error('[Ultravox] API error:', response.status, errorData); return { success: false, error: errorData.message || `API error: ${response.status}`, }; } const data: CreateCallResponse = await response.json(); console.log('[Ultravox] Call created:', data.callId); return { success: true, data }; } catch (error) { console.error('[Ultravox] Create call error:', error); return { success: false, error: error instanceof Error ? error.message : 'Failed to create call', }; } } /** * Get call details */ export async function getCall(callId: string): Promise { try { const response = await fetch(`${ULTRAVOX_API_URL}/calls/${callId}`, { method: 'GET', headers: { 'X-API-Key': ULTRAVOX_API_KEY, }, }); if (!response.ok) { return null; } return await response.json(); } catch (error) { console.error('[Ultravox] Get call error:', error); return null; } } /** * End a call */ export async function endCall(callId: string): Promise { try { const response = await fetch(`${ULTRAVOX_API_URL}/calls/${callId}`, { method: 'DELETE', headers: { 'X-API-Key': ULTRAVOX_API_KEY, }, }); return response.ok; } catch (error) { console.error('[Ultravox] End call error:', error); return false; } }