@voxdiscover/voiceserver 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +465 -0
- package/dist/index.cjs +870 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +580 -0
- package/dist/index.d.ts +580 -0
- package/dist/index.js +856 -0
- package/dist/index.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/validation.ts","../src/utils/reconnect.ts","../src/errors.ts","../src/VoiceAgent.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { SessionData } from '../types.js';\n\n/**\n * Decode JWT session token without verification.\n * Backend already validated token; client just needs payload.\n */\nexport function decodeSessionToken(token: string): SessionData {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Malformed session token');\n }\n\n try {\n const payload = JSON.parse(atob(parts[1]));\n\n // Check expiration\n if (payload.exp && payload.exp * 1000 < Date.now()) {\n throw new Error('Session token expired');\n }\n\n return payload as SessionData;\n } catch (err) {\n if (err instanceof Error && err.message.includes('expired')) {\n throw err;\n }\n throw new Error('Failed to decode session token');\n }\n}\n\n/**\n * Validate session token with backend.\n * Per user decision: async validation, fail-fast on invalid tokens.\n */\nexport async function validateToken(\n sessionId: string,\n baseUrl: string = 'http://localhost:8000'\n): Promise<void> {\n const response = await fetch(`${baseUrl}/v1/sessions/${sessionId}`);\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new Error('Session not found or expired');\n }\n throw new Error(`Failed to validate session: ${response.statusText}`);\n }\n\n const session = await response.json();\n if (session.status !== 'active') {\n throw new Error('Session is no longer active');\n }\n}\n","import { backOff } from 'exponential-backoff';\n\n/**\n * Manages automatic reconnection with exponential backoff and jitter.\n * Per RESEARCH.md Pattern 4 and research recommendations.\n */\nexport class ReconnectionManager {\n private maxRetries: number;\n private initialDelayMs: number;\n private maxDelayMs: number;\n\n constructor(config?: {\n maxRetries?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n }) {\n this.maxRetries = config?.maxRetries ?? 5;\n this.initialDelayMs = config?.initialDelayMs ?? 1000;\n this.maxDelayMs = config?.maxDelayMs ?? 30000;\n }\n\n /**\n * Execute connection function with exponential backoff retry logic.\n * Adds jitter to prevent thundering herd problem.\n */\n async reconnectWithBackoff(\n connectFn: () => Promise<void>,\n onRetry?: (attempt: number, delayMs: number) => void\n ): Promise<void> {\n return backOff(connectFn, {\n numOfAttempts: this.maxRetries,\n startingDelay: this.initialDelayMs,\n maxDelay: this.maxDelayMs,\n jitter: 'full', // Full jitter to prevent simultaneous retries\n retry: (err: any, attempt: number) => {\n // Don't retry on token errors (non-retryable)\n if (\n err?.message?.includes('token') ||\n err?.message?.includes('session')\n ) {\n return false;\n }\n\n const delay = Math.min(\n this.initialDelayMs * Math.pow(2, attempt - 1),\n this.maxDelayMs\n );\n\n onRetry?.(attempt, delay);\n return true;\n },\n });\n }\n}\n","/**\n * Error codes for VoiceAgent SDK.\n * Per user decision: both instanceof checks AND code property checks.\n */\nexport type VoiceAgentErrorCode =\n | 'TOKEN_EXPIRED'\n | 'TOKEN_INVALID'\n | 'CONNECTION_FAILED'\n | 'PERMISSION_DENIED'\n | 'NETWORK_ERROR'\n | 'UNKNOWN_ERROR';\n\n/**\n * Base error class for VoiceAgent SDK.\n *\n * Per user decision: includes human-readable message, suggested fix/action,\n * original cause, context data, and retryability indicator.\n *\n * Supports both error handling patterns:\n * - Pattern 1: instanceof checks\n * - Pattern 2: code property checks\n *\n * @example\n * ```typescript\n * try {\n * await agent.connect();\n * } catch (err) {\n * // Pattern 1: instanceof\n * if (err instanceof TokenExpiredError) {\n * console.log(err.context?.suggestion);\n * }\n *\n * // Pattern 2: code property\n * if (err.code === 'TOKEN_EXPIRED') {\n * refreshToken();\n * }\n *\n * // Retryability check\n * if (err.retryable) {\n * retry();\n * }\n * }\n * ```\n */\nexport class VoiceAgentError extends Error {\n readonly code: VoiceAgentErrorCode;\n readonly cause?: Error;\n readonly context?: Record<string, any>;\n readonly retryable: boolean;\n\n constructor(\n message: string,\n code: VoiceAgentErrorCode,\n options?: {\n cause?: Error;\n context?: Record<string, any>;\n retryable?: boolean;\n }\n ) {\n super(message);\n this.name = 'VoiceAgentError';\n this.code = code;\n this.cause = options?.cause;\n this.context = options?.context;\n this.retryable = options?.retryable ?? false;\n\n // Maintain proper stack trace in V8\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, VoiceAgentError);\n }\n\n // Fix prototype chain for instanceof checks\n Object.setPrototypeOf(this, VoiceAgentError.prototype);\n }\n}\n\n/**\n * Session token has expired.\n * Per user decision: non-retryable, includes suggested action.\n */\nexport class TokenExpiredError extends VoiceAgentError {\n constructor(message: string = 'Session token has expired', cause?: Error) {\n super(message, 'TOKEN_EXPIRED', {\n cause,\n retryable: false,\n context: {\n suggestion: 'Request a new session token from your backend',\n },\n });\n this.name = 'TokenExpiredError';\n Object.setPrototypeOf(this, TokenExpiredError.prototype);\n }\n}\n\n/**\n * Session token is invalid or malformed.\n * Per user decision: non-retryable, includes suggested action.\n */\nexport class TokenInvalidError extends VoiceAgentError {\n constructor(message: string = 'Session token is invalid', cause?: Error) {\n super(message, 'TOKEN_INVALID', {\n cause,\n retryable: false,\n context: {\n suggestion: 'Verify session token format and request a new token if needed',\n },\n });\n this.name = 'TokenInvalidError';\n Object.setPrototypeOf(this, TokenInvalidError.prototype);\n }\n}\n\n/**\n * WebRTC connection failed.\n * Per user decision: retryable, includes suggested action.\n */\nexport class ConnectionFailedError extends VoiceAgentError {\n constructor(message: string, cause?: Error) {\n super(message, 'CONNECTION_FAILED', {\n cause,\n retryable: true,\n context: {\n suggestion: 'Check network connection and retry',\n },\n });\n this.name = 'ConnectionFailedError';\n Object.setPrototypeOf(this, ConnectionFailedError.prototype);\n }\n}\n\n/**\n * Microphone or camera permission denied by user.\n * Per user decision: non-retryable, includes suggested action.\n */\nexport class PermissionDeniedError extends VoiceAgentError {\n constructor(permission: 'microphone' | 'camera') {\n super(\n `${permission} permission denied by user`,\n 'PERMISSION_DENIED',\n {\n retryable: false,\n context: {\n permission,\n suggestion: `Grant ${permission} permission in browser settings and reload`,\n },\n }\n );\n this.name = 'PermissionDeniedError';\n Object.setPrototypeOf(this, PermissionDeniedError.prototype);\n }\n}\n\n/**\n * Network error occurred during API call or WebRTC connection.\n * Per user decision: retryable.\n */\nexport class NetworkError extends VoiceAgentError {\n constructor(message: string, cause?: Error) {\n super(message, 'NETWORK_ERROR', {\n cause,\n retryable: true,\n context: {\n suggestion: 'Check internet connection and retry',\n },\n });\n this.name = 'NetworkError';\n Object.setPrototypeOf(this, NetworkError.prototype);\n }\n}\n","import DailyIframe, { type DailyCall } from '@daily-co/daily-js';\nimport EventEmitter from 'eventemitter3';\nimport type {\n VoiceAgentConfig,\n VoiceAgentEvents,\n ConnectionState,\n SessionData,\n TranscriptData,\n AnalyticsEvent,\n AnalyticsCallback,\n CustomContext,\n ContextUpdateData,\n CostBreakdown,\n CostSummary,\n AgentSwapOptions,\n} from './types.js';\nimport { decodeSessionToken, validateToken } from './utils/validation.js';\nimport { ReconnectionManager } from './utils/reconnect.js';\nimport {\n VoiceAgentError,\n TokenExpiredError,\n TokenInvalidError,\n ConnectionFailedError,\n PermissionDeniedError,\n NetworkError,\n} from './errors.js';\n\n/**\n * VoiceAgent SDK for Voice_server voice conversations.\n *\n * Per user decisions:\n * - Constructor pattern with minimal required config (only token)\n * - Explicit connect() - no auto-connect on init\n * - disconnect() performs full cleanup (leave + destroy)\n * - Read-only state property\n * - Async validation before connect\n *\n * @example\n * ```typescript\n * const agent = new VoiceAgent({ token: sessionToken });\n *\n * agent.on('connection:state', (state) => {\n * console.log('State:', state);\n * });\n *\n * await agent.connect();\n * agent.mute();\n * await agent.disconnect();\n * ```\n */\nexport class VoiceAgent extends EventEmitter<VoiceAgentEvents> {\n private config: VoiceAgentConfig;\n private sessionData: SessionData | null = null;\n private dailyCall: DailyCall | null = null;\n private _state: ConnectionState = 'disconnected';\n private reconnectionManager: ReconnectionManager;\n\n /**\n * Audio elements for remote participants.\n * Daily.js createCallObject() does not auto-play remote audio — we must\n * create <audio> elements ourselves in the track-started handler.\n */\n private remoteAudioElements: Map<string, HTMLAudioElement> = new Map();\n\n /**\n * Cumulative cost breakdown for the current session.\n * Per RESEARCH.md Pattern 4: appended on each cost-update app-message.\n * Reset to [] on disconnect() for clean state on reconnection.\n */\n private costBreakdown: CostBreakdown[] = [];\n\n /**\n * Current agent ID tracked for duplicate-swap guard.\n * Initialized from session token on connect().\n */\n private currentAgentId: string | null = null;\n\n /**\n * Registered analytics callbacks.\n * Per RESEARCH.md Pattern 5: observer pattern for lifecycle and error events.\n */\n private analyticsCallbacks: AnalyticsCallback[] = [];\n\n /**\n * Circuit breaker counter for analytics to prevent infinite loops.\n * Per RESEARCH.md Pitfall #5: if same event emitted >10 times/second, disable analytics.\n */\n private analyticsCallCount = 0;\n private analyticsCallResetTimer: ReturnType<typeof setTimeout> | null = null;\n private analyticsDisabled = false;\n\n /**\n * Optional mem0 memory client for client-side conversation memory.\n * Initialized from config.mem0ApiKey via dynamic import (optional peer dependency).\n * Per RESEARCH.md Pattern 3: client-side pattern syncs on session end.\n */\n private memoryClient: any = null;\n\n /**\n * Transcript history for mem0 sync on session end.\n * Accumulates final transcripts as {role, content} pairs.\n * Reset on disconnect() for clean state on reconnection.\n */\n private transcriptHistory: Array<{role: string, content: string}> = [];\n\n /**\n * Create VoiceAgent instance.\n * Per user decision: constructor pattern, minimal config (only token required).\n */\n constructor(config: VoiceAgentConfig) {\n super();\n this.config = {\n baseUrl: config.baseUrl ?? 'http://localhost:8000',\n reconnection: {\n enabled: config.reconnection?.enabled ?? true,\n maxAttempts: config.reconnection?.maxAttempts ?? 5,\n },\n ...config,\n };\n\n this.reconnectionManager = new ReconnectionManager({\n maxRetries: this.config.reconnection?.maxAttempts,\n });\n\n // Initialize optional mem0 client (fire-and-forget; ready before connect() is called)\n if (this.config.mem0ApiKey) {\n this.initMemoryClient().catch(err => {\n console.warn('[VoiceAgent] mem0 initialization failed:', err);\n });\n }\n }\n\n /**\n * Get current connection state.\n * Per user decision: read-only state property.\n */\n get state(): ConnectionState {\n return this._state;\n }\n\n /**\n * Register an analytics callback for lifecycle and error events.\n *\n * Emits: session_started, session_ended, connection_failed, and error events.\n *\n * IMPORTANT: Analytics callbacks MUST be read-only. Do NOT call SDK methods\n * (connect, disconnect, mute, etc.) inside a callback. Doing so will trigger\n * the circuit breaker and disable analytics for the remainder of the session.\n * See RESEARCH.md Pitfall #5.\n *\n * @param callback Function called with each analytics event\n *\n * @example\n * ```typescript\n * agent.onAnalyticsEvent((event) => {\n * // Integrate with Segment, DataDog, PostHog, etc.\n * analytics.track(event.eventType, {\n * session_id: event.sessionId,\n * user_id: event.userId,\n * });\n * });\n * ```\n */\n onAnalyticsEvent(callback: AnalyticsCallback): void {\n this.analyticsCallbacks.push(callback);\n }\n\n /**\n * Search user memories from mem0 for context-aware responses.\n *\n * Requires mem0ApiKey and userId in config. Returns empty array if mem0\n * is not configured or an error occurs.\n *\n * @param query Search query (e.g., \"user preferences\", \"previous orders\")\n * @param limit Maximum number of results (default: 5)\n * @returns Array of memory objects with 'memory' and 'score' fields\n *\n * @example\n * ```typescript\n * const memories = await agent.searchMemories('user preferences', 3);\n * memories.forEach(m => console.log(m.memory));\n * ```\n */\n async searchMemories(query: string, limit = 5): Promise<any[]> {\n if (!this.memoryClient || !this.config.userId) {\n return [];\n }\n try {\n const result = await this.memoryClient.search(query, {\n user_id: this.config.userId,\n limit,\n });\n return Array.isArray(result) ? result : (result?.results ?? []);\n } catch (err) {\n console.error('[VoiceAgent] mem0 search failed:', err);\n return [];\n }\n }\n\n /**\n * Initialize optional mem0 memory client via dynamic import.\n * Uses dynamic import so missing mem0ai package is a soft warning, not an error.\n * Per RESEARCH.md Pattern 3 (Client-side - Web SDK).\n */\n private async initMemoryClient(): Promise<void> {\n try {\n const { MemoryClient } = await import('mem0ai');\n this.memoryClient = new MemoryClient({ apiKey: this.config.mem0ApiKey! });\n } catch {\n console.warn(\n '[VoiceAgent] mem0ai package not found. ' +\n 'Install with: npm install mem0ai\\n' +\n 'See: https://docs.mem0.ai/platform/quickstart'\n );\n }\n }\n\n /**\n * Emit analytics event to all registered callbacks.\n * Per RESEARCH.md Pattern 5: try/catch per callback prevents analytics errors from breaking SDK.\n * Per RESEARCH.md Pitfall #5: circuit breaker disables analytics on excessive calls.\n */\n private emitAnalyticsEvent(event: AnalyticsEvent): void {\n if (this.analyticsDisabled || this.analyticsCallbacks.length === 0) {\n return;\n }\n\n // Circuit breaker: track call frequency to detect infinite loops\n this.analyticsCallCount++;\n if (this.analyticsCallResetTimer === null) {\n this.analyticsCallResetTimer = setTimeout(() => {\n this.analyticsCallCount = 0;\n this.analyticsCallResetTimer = null;\n }, 1000);\n }\n\n if (this.analyticsCallCount > 10) {\n this.analyticsDisabled = true;\n console.error(\n '[VoiceAgent] Analytics disabled: >10 events emitted in 1 second. ' +\n 'Ensure analytics callbacks are read-only and do not call SDK methods.'\n );\n return;\n }\n\n for (const callback of this.analyticsCallbacks) {\n try {\n callback(event);\n } catch (err) {\n // Per RESEARCH.md Pitfall #5: analytics errors must not break SDK\n console.error('[VoiceAgent] Analytics callback error:', err);\n }\n }\n }\n\n /**\n * Connect to voice session.\n * Per user decision: explicit connect(), async validation before connect.\n */\n async connect(): Promise<void> {\n if (this._state !== 'disconnected') {\n throw new Error('Already connected or connecting');\n }\n\n this.setState('connecting');\n\n try {\n // Per user decision: async validation (fail-fast on invalid tokens)\n this.sessionData = decodeSessionToken(this.config.token);\n await validateToken(this.sessionData.session_id, this.config.baseUrl);\n\n // Create Daily call object\n this.dailyCall = DailyIframe.createCallObject({\n audioSource: true,\n videoSource: false,\n dailyConfig: {\n avoidEval: true, // CSP-friendly\n },\n });\n\n // Register event listeners before joining\n this.setupDailyEventListeners();\n\n // Join Daily room with URL and token from session\n await this.dailyCall.join({ url: this.sessionData.room_url, token: this.sessionData.daily_token });\n\n // State updated in 'joined-meeting' event handler\n } catch (err) {\n this.setState('failed');\n\n // Wrap validation errors with typed errors\n if (err instanceof Error) {\n let typedError: VoiceAgentError;\n\n if (err.message.includes('expired')) {\n typedError = new TokenExpiredError(err.message, err);\n } else if (err.message.includes('Malformed') || err.message.includes('decode')) {\n typedError = new TokenInvalidError(err.message, err);\n } else if (err.message.includes('Session not found')) {\n typedError = new TokenExpiredError('Session not found or expired', err);\n } else if (err.message.includes('validate')) {\n typedError = new NetworkError(`Failed to validate session: ${err.message}`, err);\n } else {\n typedError = new ConnectionFailedError(err.message, err);\n }\n\n this.emit('connection:error', typedError);\n throw typedError;\n }\n\n const error = new ConnectionFailedError(String(err));\n this.emit('connection:error', error);\n throw error;\n }\n }\n\n /**\n * Disconnect from voice session.\n * Per user decision: full cleanup (leave + destroy + remove listeners).\n * Per RESEARCH.md Pitfall 2: Both leave() and destroy() required.\n */\n async disconnect(): Promise<void> {\n if (!this.dailyCall) {\n return;\n }\n\n // Capture session data before cleanup for analytics event\n const sessionDataSnapshot = this.sessionData;\n\n try {\n // Leave meeting gracefully\n await this.dailyCall.leave();\n\n // Critical: destroy() to prevent memory leaks (per RESEARCH.md)\n await this.dailyCall.destroy();\n } catch (err) {\n console.error('Disconnect error:', err);\n } finally {\n // Sync conversation to mem0 on session end (opt-in: requires mem0ApiKey + userId)\n // Per RESEARCH.md Pattern 3: sync on session end only (not per-message)\n if (this.memoryClient && this.config.userId && this.transcriptHistory.length > 0) {\n try {\n await this.memoryClient.add(this.transcriptHistory, { user_id: this.config.userId });\n } catch (err) {\n // Don't fail disconnect on memory sync error\n console.error('[VoiceAgent] mem0 memory sync failed (non-fatal):', err);\n }\n }\n\n // Clean up remote audio elements\n for (const audio of this.remoteAudioElements.values()) {\n audio.pause();\n audio.srcObject = null;\n }\n this.remoteAudioElements.clear();\n\n this.dailyCall = null;\n this.sessionData = null;\n // Reset cost breakdown and transcript history for clean state on reconnection\n this.costBreakdown = [];\n this.transcriptHistory = [];\n this.setState('disconnected');\n\n // Emit session_ended analytics event after cleanup\n this.emitAnalyticsEvent({\n timestamp: Date.now(),\n eventType: 'session_ended',\n sessionId: sessionDataSnapshot?.session_id ?? 'unknown',\n agentId: sessionDataSnapshot?.agent_id,\n userId: sessionDataSnapshot?.user_id,\n });\n }\n }\n\n /**\n * Mute microphone.\n */\n mute(): void {\n if (!this.dailyCall) {\n throw new Error('Not connected');\n }\n this.dailyCall.setLocalAudio(false);\n this.emit('audio:muted');\n }\n\n /**\n * Unmute microphone.\n */\n unmute(): void {\n if (!this.dailyCall) {\n throw new Error('Not connected');\n }\n this.dailyCall.setLocalAudio(true);\n this.emit('audio:unmuted');\n }\n\n /**\n * Update session context mid-session.\n *\n * Per Phase 15 ADV-02: allows developer to update user_id, customer_id,\n * session_metadata, and custom JSON during an active session.\n *\n * Validates context client-side (10KB size, 50 fields) with warnings.\n * POSTs to /v1/sessions/{session_id}/context endpoint.\n * Emits 'context:updated' event on success.\n *\n * @param contextUpdates Partial context to merge into existing session context\n * @throws Error if no active session\n * @throws Error if the context update API call fails\n *\n * @example\n * ```typescript\n * await agent.updateContext({\n * user_id: 'user_123',\n * custom: { preferred_language: 'Spanish', loyalty_tier: 'gold' }\n * });\n * ```\n */\n async updateContext(contextUpdates: Partial<CustomContext>): Promise<void> {\n if (!this.sessionData) {\n throw new Error('Cannot update context: no active session');\n }\n\n // Client-side validation with warnings (permissive per user decision)\n this.validateContext(contextUpdates);\n\n // POST context updates to backend\n const response = await fetch(\n `${this.config.baseUrl}/v1/sessions/${this.sessionData.session_id}/context`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.config.token}`,\n },\n body: JSON.stringify({ context: contextUpdates }),\n }\n );\n\n if (!response.ok) {\n throw new Error(\n `Context update failed: ${response.status} ${response.statusText}`\n );\n }\n\n // Emit context:updated event for developer hooks\n const updateData: ContextUpdateData = {\n updates: contextUpdates,\n timestamp: Date.now(),\n };\n this.emit('context:updated', updateData);\n }\n\n /**\n * Validate context client-side for size (10KB) and field count (50 max).\n * Validation is permissive: warns but does not throw on limits exceeded.\n * Per user decision: don't break session on validation warning.\n *\n * @param context Context object to validate\n */\n private validateContext(context: Partial<CustomContext>): void {\n // Check serialized size\n const serialized = JSON.stringify(context);\n const sizeBytes = new Blob([serialized]).size;\n\n if (sizeBytes > 10240) {\n console.warn(\n `[VoiceAgent] Context size (${sizeBytes} bytes) exceeds 10KB limit. ` +\n 'Backend will truncate custom fields.'\n );\n }\n\n // Check custom field count\n const customFieldCount = Object.keys(context.custom ?? {}).length;\n if (customFieldCount > 50) {\n console.warn(\n `[VoiceAgent] Custom context has ${customFieldCount} fields (limit: 50). ` +\n 'Backend will truncate to first 50 fields.'\n );\n }\n }\n\n /**\n * Switch agent mid-session without disconnecting WebRTC.\n *\n * Per Phase 15 ADV-01: hot-swap the backend bot while keeping the Daily room\n * connection alive. The new agent receives full conversation context and\n * transcript history.\n *\n * Protocol:\n * 1. Validate connected and not already using newAgentId\n * 2. Emit agent:swapping event (for analytics / UI loading indicator)\n * 3. Send Daily app-message to backend bot requesting swap\n * 4. Wait for agent-swap-complete confirmation (with timeout)\n * 5. Update currentAgentId and emit agent:swapped on success\n * 6. Emit agent:swap-failed and throw on timeout or backend error\n *\n * @param newAgentId UUID of the agent to swap to\n * @param options Swap options (preserveContext, preserveTranscripts, timeout)\n * @throws Error if not connected, already using newAgentId, or swap fails/times out\n *\n * @example\n * ```typescript\n * try {\n * await agent.switchAgent('specialist-agent-uuid');\n * console.log('Agent switched successfully');\n * } catch (err) {\n * console.error('Swap failed:', err);\n * // Old agent is still active (resilient fallback)\n * }\n * ```\n */\n async switchAgent(newAgentId: string, options: AgentSwapOptions = {}): Promise<void> {\n const {\n preserveContext = true,\n preserveTranscripts = true,\n timeout = 5000,\n } = options;\n\n if (!this.dailyCall || this._state !== 'connected') {\n throw new Error('Cannot switch agent: not connected');\n }\n\n if (this.currentAgentId === newAgentId) {\n throw new Error('Already using this agent');\n }\n\n const timestamp = Date.now();\n const sessionId = this.sessionData?.session_id ?? 'unknown';\n\n // Emit pre-swap event (for UI loading indicator)\n this.emit('agent:swapping', { newAgentId, timestamp });\n\n // Emit analytics: agent swap starting\n this.emitAnalyticsEvent({\n timestamp,\n eventType: 'agent_swap_completed', // will be overridden on failure\n sessionId,\n agentId: newAgentId,\n });\n\n try {\n // Send swap request via Daily app-message to backend bot\n this.dailyCall.sendAppMessage({\n type: 'agent-swap-request',\n new_agent_id: newAgentId,\n preserve_context: preserveContext,\n preserve_transcripts: preserveTranscripts,\n }, '*');\n\n // Wait for backend confirmation with timeout\n await this.waitForSwapConfirmation(newAgentId, timeout);\n\n // Update local agent tracking\n this.currentAgentId = newAgentId;\n\n // Emit success events\n this.emit('agent:swapped', { newAgentId, timestamp: Date.now() });\n this.emitAnalyticsEvent({\n timestamp: Date.now(),\n eventType: 'agent_swap_completed',\n sessionId,\n agentId: newAgentId,\n });\n\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n\n // Emit failure events\n this.emit('agent:swap-failed', { newAgentId, timestamp: Date.now(), error: errorMessage });\n this.emitAnalyticsEvent({\n timestamp: Date.now(),\n eventType: 'agent_swap_failed',\n sessionId,\n agentId: newAgentId,\n error: {\n code: 'AGENT_SWAP_ERROR',\n message: errorMessage,\n retryable: true,\n },\n });\n\n throw new Error(`Agent swap failed: ${errorMessage}`);\n }\n }\n\n /**\n * Wait for backend agent-swap-complete confirmation via Daily app-message.\n *\n * Resolves when agent-swap-complete is received with matching agent_id.\n * Rejects on agent-swap-failed message or timeout.\n *\n * @param agentId Expected new agent ID in confirmation\n * @param timeoutMs Milliseconds before timing out\n */\n private waitForSwapConfirmation(agentId: string, timeoutMs: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n cleanup();\n reject(new Error('Agent swap timeout — new agent failed to connect'));\n }, timeoutMs);\n\n const handler = (event: any) => {\n const data = event?.data;\n if (!data) return;\n\n if (data.type === 'agent-swap-complete' && data.agent_id === agentId) {\n cleanup();\n resolve();\n } else if (data.type === 'agent-swap-failed') {\n cleanup();\n reject(new Error(data.error || 'Backend agent swap failed'));\n }\n };\n\n const cleanup = () => {\n clearTimeout(timer);\n this.dailyCall?.off('app-message', handler);\n };\n\n this.dailyCall?.on('app-message', handler);\n });\n }\n\n /**\n * Subscribe to real-time cost updates for the session.\n *\n * Registers a callback that is called after each provider API call (STT, LLM, TTS)\n * with the cumulative cost summary including a breakdown by provider and service type.\n *\n * Per RESEARCH.md Pattern 4: Backend streams cost events; SDK aggregates and exposes\n * via this callback for developer integration (budget alerts, user-facing displays).\n *\n * @param callback Function called with CostSummary on each cost update\n *\n * @example\n * ```typescript\n * agent.onCostUpdate((summary) => {\n * console.log(`Session cost: $${summary.totalUsd.toFixed(4)}`);\n * console.log('By provider:', summary.byProvider);\n * console.log('By service:', summary.byServiceType);\n * });\n * ```\n */\n onCostUpdate(callback: (summary: CostSummary) => void): void {\n this.on('cost:update', callback);\n }\n\n /**\n * Get the current cumulative cost summary for the session.\n *\n * Returns a snapshot of all costs incurred so far, aggregated by provider\n * and service type. Returns empty summary if no costs have been tracked.\n *\n * @returns CostSummary with totalUsd, breakdown array, byProvider, and byServiceType\n */\n getCostSummary(): CostSummary {\n const totalUsd = this.costBreakdown.reduce((sum, b) => sum + b.costUsd, 0);\n\n const byProvider: Record<string, number> = {};\n const byServiceType: Record<string, number> = {};\n\n for (const b of this.costBreakdown) {\n byProvider[b.provider] = (byProvider[b.provider] ?? 0) + b.costUsd;\n byServiceType[b.serviceType] = (byServiceType[b.serviceType] ?? 0) + b.costUsd;\n }\n\n return {\n totalUsd,\n breakdown: [...this.costBreakdown],\n byProvider,\n byServiceType,\n };\n }\n\n /**\n * Set up cost tracking subscription on the Daily call object.\n * Per RESEARCH.md Pattern 4: subscribe to cost-update app-messages from backend.\n * Called from setupDailyEventListeners() after Daily call object is created.\n */\n private setupCostTracking(): void {\n if (!this.dailyCall) return;\n\n this.dailyCall.on('app-message', this.handleCostUpdate);\n }\n\n /**\n * Handle cost-update app-message from backend bot.\n * Parses cost event, appends to costBreakdown, and emits cost:update event.\n * Per RESEARCH.md Pattern 4: cost events contain provider, service_type, model, cost_usd.\n */\n private handleCostUpdate = (event: any): void => {\n const data = event?.data;\n\n if (!data || data.type !== 'cost-update') {\n return;\n }\n\n const { provider, service_type, model, cost_usd, timestamp } = data;\n\n // Validate required fields\n if (!provider || !service_type || !model || typeof cost_usd !== 'number') {\n return;\n }\n\n const breakdown: CostBreakdown = {\n provider,\n serviceType: service_type as 'stt' | 'llm' | 'tts',\n model,\n costUsd: cost_usd,\n timestamp: timestamp ?? Date.now(),\n };\n\n this.costBreakdown.push(breakdown);\n\n // Emit cost:update event with current cumulative summary\n this.emit('cost:update', this.getCostSummary());\n };\n\n private setState(newState: ConnectionState): void {\n this._state = newState;\n this.emit('connection:state', newState);\n }\n\n private setupDailyEventListeners(): void {\n if (!this.dailyCall) return;\n\n this.dailyCall\n .on('joined-meeting', this.handleJoined)\n .on('left-meeting', this.handleLeft)\n .on('participant-joined', this.handleParticipantJoined)\n .on('participant-left', this.handleParticipantLeft)\n .on('track-started', this.handleTrackStarted)\n .on('track-stopped', this.handleTrackStopped)\n .on('error', this.handleDailyError)\n .on('app-message', this.handleTranscript);\n\n // Subscribe to cost-update app-messages from backend bot\n this.setupCostTracking();\n }\n\n private handleJoined = () => {\n this.setState('connected');\n // Track current agent ID for duplicate-swap guard\n this.currentAgentId = this.sessionData?.agent_id ?? null;\n\n // Emit session_started analytics event on successful connection\n this.emitAnalyticsEvent({\n timestamp: Date.now(),\n eventType: 'session_started',\n sessionId: this.sessionData?.session_id ?? 'unknown',\n agentId: this.sessionData?.agent_id,\n userId: this.sessionData?.user_id,\n });\n };\n\n private handleLeft = () => {\n this.setState('disconnected');\n };\n\n private handleParticipantJoined = () => {\n // Future: track participants\n };\n\n private handleParticipantLeft = (event: any) => {\n const participantId = event?.participant?.session_id;\n if (!participantId) return;\n const audio = this.remoteAudioElements.get(participantId);\n if (audio) {\n audio.pause();\n audio.srcObject = null;\n this.remoteAudioElements.delete(participantId);\n }\n };\n\n /**\n * Create and play an <audio> element when a remote participant's audio track starts.\n * Daily.js createCallObject() does NOT auto-play remote audio in headless mode —\n * the app must handle track-started and wire the track to an audio element.\n */\n private handleTrackStarted = (event: any): void => {\n const { participant, track, type } = event;\n if (participant?.local || type !== 'audio' || !track) return;\n\n const participantId = participant.session_id;\n let audio = this.remoteAudioElements.get(participantId);\n if (!audio) {\n audio = new Audio();\n this.remoteAudioElements.set(participantId, audio);\n }\n\n audio.srcObject = new MediaStream([track]);\n audio.play().catch((err) => {\n console.warn('[VoiceAgent] Remote audio playback failed:', err);\n });\n };\n\n private handleTrackStopped = (event: any): void => {\n const { participant, type } = event;\n if (participant?.local || type !== 'audio') return;\n\n const participantId = participant.session_id;\n const audio = this.remoteAudioElements.get(participantId);\n if (audio) {\n audio.pause();\n audio.srcObject = null;\n this.remoteAudioElements.delete(participantId);\n }\n };\n\n private handleDailyError = (error: any) => {\n const errorMsg = error?.errorMsg || 'Unknown Daily.js error';\n\n let typedError: VoiceAgentError;\n\n if (errorMsg.includes('token') || errorMsg.includes('expired')) {\n typedError = new TokenExpiredError('Daily token invalid or expired');\n } else if (errorMsg.includes('permission') || errorMsg.includes('microphone')) {\n typedError = new PermissionDeniedError('microphone');\n } else if (errorMsg.includes('network') || errorMsg.includes('connection')) {\n typedError = new ConnectionFailedError(errorMsg);\n } else {\n typedError = new ConnectionFailedError(errorMsg);\n }\n\n this.emit('connection:error', typedError);\n\n // Emit connection_failed analytics event with error details and retryable flag\n this.emitAnalyticsEvent({\n timestamp: Date.now(),\n eventType: 'connection_failed',\n sessionId: this.sessionData?.session_id ?? 'unknown',\n agentId: this.sessionData?.agent_id,\n userId: this.sessionData?.user_id,\n error: {\n code: typedError.code,\n message: typedError.message,\n retryable: typedError.retryable,\n },\n });\n\n // Only attempt reconnection for retryable errors\n if (typedError.retryable && this.config.reconnection?.enabled && this._state === 'connected') {\n this.attemptReconnect();\n }\n };\n\n private handleTranscript = (event: any) => {\n // Per user decision: streaming with interim/final separation\n const { text, speaker, is_final } = event.data || {};\n\n if (!text || !speaker) return;\n\n const transcriptData: TranscriptData = {\n text,\n speaker: speaker === 'local' ? 'user' : 'agent',\n timestamp: new Date(),\n };\n\n if (is_final) {\n // Accumulate final transcripts for mem0 session-end sync\n this.transcriptHistory.push({\n role: speaker === 'local' ? 'user' : 'assistant',\n content: text,\n });\n this.emit('transcript:final', transcriptData);\n } else {\n this.emit('transcript:interim', transcriptData);\n }\n };\n\n private async attemptReconnect(): Promise<void> {\n if (this._state === 'reconnecting') return;\n\n this.setState('reconnecting');\n\n try {\n await this.reconnectionManager.reconnectWithBackoff(\n async () => {\n if (!this.dailyCall || !this.sessionData) {\n throw new Error('Cannot reconnect: no active session');\n }\n await this.dailyCall.join({ url: this.sessionData.room_url, token: this.sessionData.daily_token });\n },\n (attempt, delay) => {\n console.log(`Reconnection attempt ${attempt}, waiting ${delay}ms`);\n }\n );\n\n // State updated by 'joined-meeting' event\n } catch (err) {\n this.setState('failed');\n const error = err instanceof VoiceAgentError\n ? err\n : new ConnectionFailedError('Failed to reconnect after multiple attempts', err as Error);\n this.emit('connection:error', error);\n }\n }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@voxdiscover/voiceserver",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Framework-agnostic TypeScript SDK for Voxdiscover voice agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"dev": "tsup --watch",
|
|
29
|
+
"test": "vitest",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"docs": "typedoc src/index.ts"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@daily-co/daily-js": ">=0.60.0",
|
|
35
|
+
"mem0ai": ">=1.0.0"
|
|
36
|
+
},
|
|
37
|
+
"peerDependenciesMeta": {
|
|
38
|
+
"mem0ai": {
|
|
39
|
+
"optional": true
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"eventemitter3": "^5.0.1",
|
|
44
|
+
"exponential-backoff": "^3.1.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@daily-co/daily-js": "^0.77.0",
|
|
48
|
+
"@types/node": "^22.0.0",
|
|
49
|
+
"jsdom": "^28.1.0",
|
|
50
|
+
"mem0ai": "^2.2.3",
|
|
51
|
+
"tsup": "^8.3.0",
|
|
52
|
+
"typedoc": "^0.28.0",
|
|
53
|
+
"typescript": "^5.7.0",
|
|
54
|
+
"vitest": "^3.0.0"
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=18.0.0"
|
|
58
|
+
},
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"access": "public"
|
|
61
|
+
},
|
|
62
|
+
"repository": {
|
|
63
|
+
"type": "git",
|
|
64
|
+
"url": "https://github.com/MaxMozgovoy/Voice_server.git",
|
|
65
|
+
"directory": "packages/@voice-server/core"
|
|
66
|
+
},
|
|
67
|
+
"bugs": {
|
|
68
|
+
"url": "https://github.com/MaxMozgovoy/Voice_server/issues"
|
|
69
|
+
},
|
|
70
|
+
"homepage": "https://github.com/MaxMozgovoy/Voice_server/tree/main/packages/@voice-server/core#readme",
|
|
71
|
+
"keywords": [
|
|
72
|
+
"voice",
|
|
73
|
+
"ai",
|
|
74
|
+
"sdk",
|
|
75
|
+
"webrtc",
|
|
76
|
+
"daily",
|
|
77
|
+
"voxdiscover",
|
|
78
|
+
"voice-agent"
|
|
79
|
+
],
|
|
80
|
+
"author": "Voxdiscover",
|
|
81
|
+
"license": "MIT"
|
|
82
|
+
}
|