/** * LiveKit Voice AI Service * Connects to LiveKit Cloud with Julia AI agent * Uses dedicated Julia Token Server for token generation */ // Julia Token Server (dedicated endpoint for LiveKit tokens) const JULIA_TOKEN_SERVER = 'https://wellnuo.smartlaunchhub.com/julia'; // Voice configuration export const VOICE_ID = 'Asteria'; export const VOICE_NAME = 'Asteria'; // ============================================================================ // SINGLE_DEPLOYMENT_MODE // When true: sends only deploymentId (no beneficiaryNamesDict) // When false: sends both deploymentId AND beneficiaryNamesDict // // Use true for WellNuo Lite (single beneficiary per user) // Use false for full WellNuo app (multiple beneficiaries) // ============================================================================ export const SINGLE_DEPLOYMENT_MODE = true; // Beneficiary data to pass to voice agent export interface BeneficiaryData { deploymentId: string; beneficiaryNamesDict: Record; } // API Response types export interface LiveKitTokenResponse { success: boolean; data?: { token: string; roomName: string; wsUrl: string; }; error?: string; } /** * Get a LiveKit access token from Julia Token Server * No authentication required - token server is dedicated for voice AI * @param userId - User identifier * @param beneficiaryData - Optional beneficiary data to pass to voice agent */ export async function getToken( userId: string, beneficiaryData?: BeneficiaryData ): Promise { try { console.log('[LiveKit] Getting token for user:', userId); console.log('[LiveKit] SINGLE_DEPLOYMENT_MODE:', SINGLE_DEPLOYMENT_MODE); // Prepare request body based on SINGLE_DEPLOYMENT_MODE let requestBody: { userId: string; beneficiaryData?: BeneficiaryData }; if (SINGLE_DEPLOYMENT_MODE && beneficiaryData) { // In single deployment mode: send only deploymentId, no beneficiaryNamesDict requestBody = { userId, beneficiaryData: { deploymentId: beneficiaryData.deploymentId, beneficiaryNamesDict: {}, // Empty - no list of names }, }; console.log('[LiveKit] Single deployment mode - sending only deploymentId:', beneficiaryData.deploymentId); } else { // Full mode: send everything requestBody = { userId, beneficiaryData }; if (beneficiaryData) { console.log('[LiveKit] Full mode - sending beneficiary data:', beneficiaryData); } } // Request LiveKit token from Julia Token Server const response = await fetch(`${JULIA_TOKEN_SERVER}/token`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(requestBody), }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); console.error('[LiveKit] Token request failed:', response.status, errorData); return { success: false, error: errorData.error || `Failed to get token: ${response.status}`, }; } const data = await response.json(); if (!data.success) { return { success: false, error: data.error || 'Token generation failed', }; } console.log('[LiveKit] Token received:', { room: data.data.roomName, identity: data.data.identity, url: data.data.wsUrl, }); return { success: true, data: { token: data.data.token, roomName: data.data.roomName, wsUrl: data.data.wsUrl, }, }; } catch (error) { console.error('[LiveKit] Get token error:', error); return { success: false, error: error instanceof Error ? error.message : 'Failed to get token', }; } } /** * Check if LiveKit service is available */ export async function checkServerHealth(): Promise { try { const response = await fetch(`${JULIA_TOKEN_SERVER}/health`, { method: 'GET', }); if (response.ok) { const data = await response.json(); console.log('[LiveKit] Health check:', data); return data.status === 'ok'; } return false; } catch (error) { console.error('[LiveKit] Health check failed:', error); return false; } }