@vox-ai/react 0.3.2 → 1.0.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.
@@ -1 +1 @@
1
- {"version":3,"file":"lib.umd.js","sources":["../src/hooks/useVoxAI.tsx","../src/utils/constants.ts"],"sourcesContent":["import {\n LiveKitRoom,\n RoomAudioRenderer,\n useAudioWaveform,\n useChat,\n useDataChannel,\n useLocalParticipant,\n useParticipantTracks,\n useTrackTranscription,\n useVoiceAssistant,\n} from \"@livekit/components-react\";\nimport { Track } from \"livekit-client\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport { HTTPS_API_ORIGIN, SDK_VERSION } from \"../utils/constants\";\n\ntype VoxConnectionDetail = {\n serverUrl: string;\n roomName: string;\n participantName: string;\n participantToken: string;\n};\n\n/**\n * VoxAgentState\n * @description The state of the agent\n */\nexport type VoxAgentState =\n | \"disconnected\"\n | \"connecting\"\n | \"initializing\"\n | \"listening\"\n | \"thinking\"\n | \"speaking\";\n\n/**\n * Function call related types\n */\nexport interface FunctionToolsExecuted {\n type: \"function_tools_executed\";\n function_calls: FunctionCallInfo[];\n function_call_outputs: FunctionCallResult[];\n}\n\nexport interface FunctionCallInfo {\n id: string;\n type: string;\n call_id: string;\n arguments: Record<string, any>;\n name: string;\n}\n\nexport interface FunctionCallResult {\n id: string;\n name: string;\n type: string;\n call_id: string;\n output: string;\n is_error: boolean;\n}\n\n/**\n * VoxMessage\n * @description The message type between the agent and the user\n */\nexport type VoxMessage = {\n id?: string;\n name: \"agent\" | \"user\" | \"tool\";\n message?: string;\n timestamp: number;\n isFinal?: boolean;\n tool?: FunctionToolsExecuted;\n};\n\n/**\n * VoxAIOptions\n * @description The callback functions for the useVoxAI hook\n */\nexport interface VoxAIOptions {\n onConnect?: () => void;\n onDisconnect?: () => void;\n onError?: (error: Error) => void;\n onMessage?: (message: VoxMessage) => void;\n}\n\n// Message channel event types\ntype MessageChannelEvent =\n | { type: \"state_update\"; state: VoxAgentState }\n | { type: \"transcription_update\"; transcriptions: TranscriptionSegment[] }\n | {\n type: \"waveform_update\";\n waveformData: number[];\n speaker: \"agent\" | \"user\";\n }\n | { type: \"function_tools_executed\"; tool: FunctionToolsExecuted };\n\ntype TranscriptionSegment = {\n id: string;\n text: string;\n isFinal: boolean;\n timestamp: number;\n speaker: \"agent\" | \"user\";\n};\n\n/**\n * ConnectParams\n * @param agentId - The agent ID\n * @param agentVersion - The agent version, if not provided, the current version will be used\n * @param apiKey - The API key\n * @param dynamicVariables - The dynamic variables\n * @param metadata - 이 메타데이터는 아웃바운드 웹훅, 통화 기록에 포함됩니다.\n */\nexport interface ConnectParams {\n agentId: string;\n agentVersion?: number;\n apiKey: string;\n dynamicVariables?: Record<string, any>;\n metadata?: Record<string, any>;\n}\n\n/**\n * useVoxAI\n * @description The hook for integrating with vox.ai voice assistant\n * @param options - The options for the useVoxAI hook\n * @returns The useVoxAI hook\n * @example\n * const { connect, disconnect, state, messages, send } = useVoxAI({\n * onConnect: () => console.log(\"Connected\"),\n * onDisconnect: () => console.log(\"Disconnected\"),\n * onError: (error) => console.error(\"Error:\", error),\n * onMessage: (message) => console.log(\"Message:\", message),\n * });\n */\nexport function useVoxAI(options: VoxAIOptions = {}) {\n // Connection state\n const [connectionDetail, setConnectionDetail] =\n useState<VoxConnectionDetail | null>(null);\n const [state, setState] = useState<VoxAgentState>(\"disconnected\");\n\n // Session timestamp to filter out stale asynchronous events\n const sessionTimestampRef = useRef<number>(Date.now());\n\n // Message handling\n const [transcriptMap, setTranscriptMap] = useState<Map<string, VoxMessage>>(\n new Map()\n );\n const [messages, setMessages] = useState<VoxMessage[]>([]);\n const prevMessagesRef = useRef<string>(\"\");\n\n // Track which messages we've already sent to the onMessage callback\n const processedMessageIdsRef = useRef<Set<string>>(new Set());\n\n // DOM manipulation for LiveKit portal\n const portalRootRef = useRef<HTMLDivElement | null>(null);\n const rootRef = useRef<Root | null>(null);\n\n // Communication channel\n const channelRef = useRef<MessageChannel | null>(null);\n\n // Add this near the start of your useVoxAI hook\n const livekitComponentRef = useRef<React.ReactNode>(null);\n\n // Replace the single waveform state with a map for multiple speakers\n const [waveformDataMap, setWaveformDataMap] = useState<\n Record<string, number[]>\n >({\n agent: [],\n user: [],\n });\n\n // Add back the waveform config reference\n const waveformConfigRef = useRef<{\n speaker?: \"agent\" | \"user\";\n barCount: number;\n updateInterval: number;\n } | null>(null);\n\n // Add a new state to track microphone status\n const [isMicEnabled, setIsMicEnabled] = useState<boolean>(true);\n\n // Update messages whenever transcriptMap changes\n useEffect(() => {\n const allMessages = Array.from(transcriptMap.values()).sort(\n (a, b) => a.timestamp - b.timestamp\n );\n\n // Only update if the messages have actually changed\n const messagesString = JSON.stringify(allMessages);\n if (messagesString !== prevMessagesRef.current) {\n prevMessagesRef.current = messagesString;\n setMessages(allMessages);\n\n // Only trigger onMessage for new final messages that haven't been processed yet\n if (options.onMessage) {\n allMessages\n .filter(\n (msg) =>\n msg.isFinal &&\n msg.id &&\n !processedMessageIdsRef.current.has(msg.id)\n )\n .forEach((msg) => {\n if (msg.id) {\n // Mark this message as processed\n processedMessageIdsRef.current.add(msg.id);\n // Call the callback\n options.onMessage?.(msg);\n }\n });\n }\n }\n }, [transcriptMap, options.onMessage]);\n\n // Initialize message channel - ensure ports are properly connected\n useEffect(() => {\n const channel = new MessageChannel();\n\n channel.port1.onmessage = (e) => {\n const data = e.data as MessageChannelEvent;\n\n if (data.type === \"state_update\") {\n setState(data.state);\n } else if (data.type === \"transcription_update\") {\n handleTranscriptionUpdate(data.transcriptions);\n } else if (data.type === \"waveform_update\" && data.speaker) {\n // Store the waveform data for the specific speaker\n setWaveformDataMap((prevMap) => ({\n ...prevMap,\n [data.speaker]: data.waveformData,\n }));\n } else if (data.type === \"function_tools_executed\" && data.tool) {\n // Handle function calls\n const functionCallsId = `function-calls-${Date.now()}`;\n setTranscriptMap((prevMap) => {\n const newMap = new Map(prevMap);\n newMap.set(functionCallsId, {\n id: functionCallsId,\n name: \"tool\",\n tool: data.tool,\n timestamp: Date.now(),\n isFinal: true,\n });\n return newMap;\n });\n }\n };\n\n // Start the port\n channel.port1.start();\n\n // Store the channel reference\n channelRef.current = channel;\n\n return () => {\n channelRef.current?.port1.close();\n channelRef.current?.port2.close();\n channelRef.current = null;\n };\n }, []);\n\n // Process incoming transcriptions and filter out stale events\n const handleTranscriptionUpdate = useCallback(\n (transcriptions: TranscriptionSegment[]) => {\n setTranscriptMap((prevMap) => {\n const newMap = new Map(prevMap);\n\n transcriptions.forEach((t) => {\n // Only process transcriptions generated after the current session timestamp\n if (t.timestamp < sessionTimestampRef.current) {\n return;\n }\n const messageType = t.speaker === \"agent\" ? \"agent\" : \"user\";\n // Use existing timestamp if we already have this segment\n const existingTimestamp = prevMap.get(t.id)?.timestamp || t.timestamp;\n\n newMap.set(t.id, {\n id: t.id,\n name: messageType,\n message: t.text,\n timestamp: existingTimestamp,\n isFinal: t.isFinal,\n });\n });\n\n return newMap;\n });\n },\n []\n );\n\n // Set up DOM portal for LiveKit\n useEffect(() => {\n const div = document.createElement(\"div\");\n div.style.display = \"none\";\n document.body.appendChild(div);\n portalRootRef.current = div;\n rootRef.current = createRoot(div);\n\n return () => {\n if (rootRef.current) {\n rootRef.current.unmount();\n }\n if (portalRootRef.current) {\n document.body.removeChild(portalRootRef.current);\n }\n };\n }, []);\n\n // Connect to VoxAI service - updated to include dynamicVariables\n const connect = useCallback(\n async ({ agentId, apiKey, dynamicVariables, metadata }: ConnectParams) => {\n try {\n // Prevent connecting if already in a connection state\n if (state !== \"disconnected\") {\n const errorMessage = `Connection attempt rejected: Already in a connection state (${state})`;\n console.warn(errorMessage);\n\n if (options.onError) {\n options.onError(new Error(errorMessage));\n }\n return Promise.reject(new Error(errorMessage));\n }\n\n // Update session timestamp for new connection\n sessionTimestampRef.current = Date.now();\n setState(\"connecting\");\n\n const response = await fetch(HTTPS_API_ORIGIN, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n agent_id: agentId,\n metadata: {\n runtime_context: {\n source: {\n type: \"react-sdk\",\n version: SDK_VERSION,\n },\n },\n call_web: {\n dynamic_variables: dynamicVariables || {},\n metadata: metadata || {},\n },\n },\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Connection failed (${response.status}): ${errorText}`\n );\n }\n\n const data = await response.json();\n setConnectionDetail(data);\n\n if (options.onConnect) {\n options.onConnect();\n }\n } catch (err) {\n setConnectionDetail(null);\n setTranscriptMap(new Map());\n setMessages([]);\n setState(\"disconnected\");\n\n const error = err instanceof Error ? err : new Error(String(err));\n\n if (options.onError) {\n options.onError(error);\n }\n }\n },\n [options, state]\n );\n\n // Disconnect from VoxAI service, updating the session timestamp to ignore stale events\n const disconnect = useCallback(() => {\n // Update session timestamp on disconnect\n sessionTimestampRef.current = Date.now();\n setConnectionDetail(null);\n setTranscriptMap(new Map());\n setMessages([]);\n setState(\"disconnected\");\n\n if (options.onDisconnect) {\n options.onDisconnect();\n }\n }, [options]);\n\n // Update the send function with debugging and error checking\n const send = useCallback(\n ({ message, digit }: { message?: string; digit?: number }) => {\n if (state === \"disconnected\") {\n console.warn(\"Cannot send message: Not connected to a conversation\");\n return;\n }\n\n if (message) {\n const messageId = `user-text-${Date.now()}`;\n setTranscriptMap((prevMap) => {\n const newMap = new Map(prevMap);\n newMap.set(messageId, {\n id: messageId,\n name: \"user\",\n message: message,\n timestamp: Date.now(),\n isFinal: true,\n });\n return newMap;\n });\n\n if (channelRef.current) {\n channelRef.current.port1.postMessage({\n type: \"send_text\",\n text: message,\n });\n } else {\n console.error(\"No message channel available to send message\");\n }\n }\n\n if (digit !== undefined) {\n if (channelRef.current) {\n channelRef.current.port1.postMessage({\n type: \"send_dtmf\",\n digit: digit,\n });\n } else {\n console.error(\"No message channel available to send DTMF\");\n }\n }\n },\n [state]\n );\n\n // Update the audioWaveform function to return data for the requested speaker\n const audioWaveform = useCallback(\n ({\n speaker = \"agent\",\n barCount = 10,\n updateInterval = 20,\n }: {\n speaker?: \"agent\" | \"user\";\n barCount?: number;\n updateInterval?: number;\n }): number[] => {\n waveformConfigRef.current = { speaker, barCount, updateInterval };\n\n if (channelRef.current) {\n channelRef.current.port1.postMessage({\n type: \"waveform_config\",\n config: { speaker, barCount, updateInterval },\n });\n }\n\n const speakerData = waveformDataMap[speaker] || [];\n return speakerData.length > 0\n ? speakerData.slice(0, barCount)\n : Array(barCount).fill(0);\n },\n [waveformDataMap]\n );\n\n // Add toggleMic function that will be exposed in the hook's return value\n const toggleMic = useCallback((value: boolean) => {\n setIsMicEnabled(value);\n if (channelRef.current) {\n channelRef.current.port1.postMessage({\n type: \"toggle_mic\",\n enabled: value,\n });\n } else {\n console.error(\"No message channel available to toggle microphone\");\n }\n }, []);\n\n // Add setVolume function that will be exposed in the hook's return value\n const setVolume = useCallback((volume: number) => {\n const validVolume = Math.min(Math.max(volume, 0), 1);\n if (channelRef.current) {\n channelRef.current.port1.postMessage({\n type: \"set_volume\",\n volume: validVolume,\n });\n } else {\n console.error(\"No message channel available to set volume\");\n }\n }, []);\n\n // Modify the useEffect hook that renders the LiveKit component\n useEffect(() => {\n if (!rootRef.current) return;\n\n if (connectionDetail) {\n if (!livekitComponentRef.current) {\n if (channelRef.current) {\n channelRef.current.port2.start();\n }\n\n livekitComponentRef.current = (\n <LiveKitRoom\n serverUrl={connectionDetail.serverUrl}\n token={connectionDetail.participantToken}\n audio={true}\n video={false}\n connect={true}\n onDisconnected={disconnect}\n onError={(error) => {\n console.error(\"LiveKit connection error:\", error);\n disconnect();\n if (options.onError) {\n options.onError(\n new Error(`LiveKit connection error: ${error.message}`)\n );\n }\n }}\n >\n <RoomAudioRenderer />\n {channelRef.current && (\n <StateMonitor\n port={channelRef.current.port2}\n initialConfig={\n waveformConfigRef.current || {\n barCount: 10,\n updateInterval: 20,\n }\n }\n />\n )}\n </LiveKitRoom>\n );\n }\n rootRef.current.render(livekitComponentRef.current);\n } else {\n livekitComponentRef.current = null;\n rootRef.current.render(<></>);\n }\n }, [connectionDetail, disconnect, options.onError]);\n\n return {\n connect,\n disconnect,\n state,\n messages,\n send,\n audioWaveform,\n toggleMic,\n setVolume,\n };\n}\n\n/**\n * Component that monitors LiveKit state and communicates back to the main hook\n */\nfunction StateMonitor({\n port,\n initialConfig,\n}: {\n port: MessagePort | undefined;\n initialConfig: {\n speaker?: \"agent\" | \"user\";\n barCount: number;\n updateInterval: number;\n };\n}) {\n const { agent, state } = useVoiceAssistant();\n const { send: sendChat } = useChat();\n\n // Initialize waveform config with the passed initial values, defaulting to \"agent\" if not specified\n const [waveformConfig, setWaveformConfig] = useState({\n speaker: initialConfig.speaker || \"agent\",\n barCount: initialConfig.barCount,\n updateInterval: initialConfig.updateInterval,\n });\n\n // Agent transcriptions\n const agentAudioTrack = useParticipantTracks(\n [Track.Source.Microphone],\n agent?.identity\n )[0];\n const agentTranscription = useTrackTranscription(agentAudioTrack);\n\n // Use the current config for the waveform, applying different settings based on speaker\n const agentAudioWaveform = useAudioWaveform(agentAudioTrack, {\n barCount:\n waveformConfig.speaker === \"agent\" ? waveformConfig.barCount : 120, // default if not the selected speaker\n updateInterval:\n waveformConfig.speaker === \"agent\" ? waveformConfig.updateInterval : 20,\n });\n\n // User transcriptions\n const localParticipant = useLocalParticipant();\n const localMessages = useTrackTranscription({\n publication: localParticipant.microphoneTrack,\n source: Track.Source.Microphone,\n participant: localParticipant.localParticipant,\n });\n const localAudioTrack = useParticipantTracks(\n [Track.Source.Microphone],\n localParticipant.localParticipant.identity\n )[0];\n const userAudioWaveform = useAudioWaveform(localAudioTrack, {\n barCount: waveformConfig.speaker === \"user\" ? waveformConfig.barCount : 120, // default if not the selected speaker\n updateInterval:\n waveformConfig.speaker === \"user\" ? waveformConfig.updateInterval : 20,\n });\n\n // Add separate effects to send agent and user waveform data\n useEffect(() => {\n if (!port || !agentAudioWaveform || !agentAudioWaveform.bars) return;\n\n // Send the agent waveform data\n port.postMessage({\n type: \"waveform_update\",\n waveformData: agentAudioWaveform.bars,\n speaker: \"agent\",\n });\n }, [port, agentAudioWaveform]);\n\n useEffect(() => {\n if (!port || !userAudioWaveform || !userAudioWaveform.bars) return;\n\n // Send the user waveform data\n port.postMessage({\n type: \"waveform_update\",\n waveformData: userAudioWaveform.bars,\n speaker: \"user\",\n });\n }, [port, userAudioWaveform]);\n\n // Listen for messages including config updates and mic toggle commands\n useEffect(() => {\n if (!port) return;\n\n const handleMessage = (event: MessageEvent) => {\n const data = event.data;\n\n if (data.type === \"waveform_config\" && data.config) {\n // Verify we have both required properties before updating\n if (\n typeof data.config.barCount === \"number\" &&\n typeof data.config.updateInterval === \"number\"\n ) {\n setWaveformConfig(data.config);\n }\n } else if (data.type === \"send_text\") {\n if (sendChat) {\n sendChat(data.text);\n } else {\n console.error(\"sendChat function is not available\");\n }\n } else if (data.type === \"send_dtmf\") {\n if (localParticipant.localParticipant) {\n // Use standard DTMF code (RFC 4733)\n const standardDtmfCode = 101; // Standard DTMF payload type\n localParticipant.localParticipant.publishDtmf(\n standardDtmfCode,\n data.digit\n );\n } else {\n console.error(\"Local participant is not available for DTMF\");\n }\n } else if (\n data.type === \"toggle_mic\" &&\n typeof data.enabled === \"boolean\"\n ) {\n // Handle microphone toggle\n if (localParticipant.localParticipant) {\n localParticipant.localParticipant\n .setMicrophoneEnabled(data.enabled)\n .catch((error) => {\n console.error(\"Failed to toggle microphone:\", error);\n });\n } else {\n console.error(\"Local participant is not available for mic toggle\");\n }\n } else if (\n data.type === \"set_volume\" &&\n typeof data.volume === \"number\"\n ) {\n // Handle volume control\n if (agent) {\n // The agent is a RemoteParticipant, so we can call setVolume directly\n try {\n agent.setVolume(data.volume);\n console.log(`Set agent volume to ${data.volume}`);\n } catch (error) {\n console.error(\"Failed to set agent volume:\", error);\n }\n } else {\n console.error(\"Agent is not available for volume control\");\n }\n }\n };\n\n // Make sure we start the port\n port.start();\n\n port.addEventListener(\"message\", handleMessage);\n\n return () => {\n port.removeEventListener(\"message\", handleMessage);\n };\n }, [port, sendChat, localParticipant, agent]);\n\n // Send agent state updates\n useEffect(() => {\n if (port) {\n port.postMessage({ type: \"state_update\", state });\n }\n }, [state, port]);\n\n // Send agent transcriptions\n useEffect(() => {\n if (port && agentTranscription.segments.length > 0) {\n const transcriptions = agentTranscription.segments.map((segment) => ({\n id: segment.id,\n text: segment.text,\n isFinal: segment.final,\n timestamp: Date.now(),\n speaker: \"agent\" as const,\n }));\n\n port.postMessage({\n type: \"transcription_update\",\n transcriptions,\n });\n }\n }, [agentTranscription.segments, port]);\n\n // Send user transcriptions\n useEffect(() => {\n if (port && localMessages.segments.length > 0) {\n const transcriptions = localMessages.segments.map((segment) => ({\n id: segment.id,\n text: segment.text,\n isFinal: segment.final,\n timestamp: Date.now(),\n speaker: \"user\" as const,\n }));\n\n port.postMessage({\n type: \"transcription_update\",\n transcriptions,\n });\n }\n }, [localMessages.segments, port]);\n\n // Add data channel hook for function calls\n const { message: functionToolsExecuted } = useDataChannel(\n \"function_tools_executed\",\n (msg) => {\n if (!port) return;\n\n const textDecoder = new TextDecoder();\n const messageString =\n msg.payload instanceof Uint8Array\n ? textDecoder.decode(msg.payload)\n : String(msg.payload);\n\n let tool: FunctionToolsExecuted;\n try {\n tool = JSON.parse(messageString);\n\n // Send function calls to main hook via the port\n port.postMessage({\n type: \"function_tools_executed\",\n tool: tool,\n });\n } catch (e) {\n console.error(\"Failed to parse function call log:\", e);\n }\n }\n );\n\n return null;\n}\n","// export const HTTPS_API_ORIGIN = \"https://frontend-dev.tryvox.co/api/agent/sdk\";\nexport const HTTPS_API_ORIGIN = \"https://www.tryvox.co/api/agent/sdk\";\n// export const HTTPS_API_ORIGIN = \"http://localhost:3000/api/agent/sdk\";\nexport const SDK_VERSION = \"0.3.2\";\n"],"names":["StateMonitor","_ref4","port","initialConfig","agent","state","useVoiceAssistant","send","sendChat","useChat","waveformConfig","setWaveformConfig","useState","speaker","barCount","updateInterval","agentAudioTrack","useParticipantTracks","Track","Source","Microphone","identity","agentTranscription","useTrackTranscription","agentAudioWaveform","useAudioWaveform","localParticipant","useLocalParticipant","localMessages","publication","microphoneTrack","source","participant","localAudioTrack","userAudioWaveform","useEffect","bars","postMessage","type","waveformData","handleMessage","event","data","config","text","console","error","publishDtmf","digit","enabled","setMicrophoneEnabled","catch","volume","setVolume","log","start","addEventListener","removeEventListener","segments","length","transcriptions","map","segment","id","isFinal","final","timestamp","Date","now","useDataChannel","msg","textDecoder","TextDecoder","messageString","payload","Uint8Array","decode","String","tool","JSON","parse","e","options","connectionDetail","setConnectionDetail","setState","sessionTimestampRef","useRef","transcriptMap","setTranscriptMap","Map","messages","setMessages","prevMessagesRef","processedMessageIdsRef","Set","portalRootRef","rootRef","channelRef","livekitComponentRef","waveformDataMap","setWaveformDataMap","user","waveformConfigRef","isMicEnabled","setIsMicEnabled","allMessages","Array","from","values","sort","a","b","messagesString","stringify","current","onMessage","filter","has","forEach","add","channel","MessageChannel","port1","onmessage","handleTranscriptionUpdate","prevMap","functionCallsId","newMap","set","name","_channelRef$current","_channelRef$current2","close","port2","useCallback","t","_prevMap$get","messageType","existingTimestamp","get","message","div","document","createElement","style","display","body","appendChild","createRoot","unmount","removeChild","connect","_ref","agentId","apiKey","dynamicVariables","metadata","Promise","resolve","errorMessage","warn","onError","Error","reject","fetch","method","headers","Authorization","agent_id","runtime_context","version","call_web","dynamic_variables","then","response","_temp2","_result2","_exit","json","onConnect","_temp","ok","errorText","status","_catch","err","disconnect","onDisconnect","_ref2","messageId","undefined","audioWaveform","_ref3","speakerData","slice","fill","toggleMic","value","validVolume","Math","min","max","_jsxs","LiveKitRoom","serverUrl","token","participantToken","audio","video","onDisconnected","children","_jsx","RoomAudioRenderer","render","_Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"lib.umd.js","sources":["../src/hooks/useConversation.ts"],"sourcesContent":["import {\n Conversation,\n type ConversationMessage,\n type ConversationMode,\n type ConversationSource,\n type ConversationStatus,\n type InputDeviceConfig,\n type OutputDeviceConfig,\n type SetVolumeParams,\n type StartSessionOptions,\n} from \"@vox-ai/client\";\nimport { useCallback, useMemo, useRef, useState } from \"react\";\n\ntype HookCallbacks = Pick<\n StartSessionOptions,\n | \"onConnect\"\n | \"onDisconnect\"\n | \"onError\"\n | \"onMessage\"\n | \"onStatusChange\"\n | \"onModeChange\"\n>;\n\nexport type UseConversationOptions = HookCallbacks & {\n textOnly?: boolean;\n};\n\nexport type StartConversationOptions = Omit<\n StartSessionOptions,\n keyof HookCallbacks\n>;\n\nexport function useConversation(options: UseConversationOptions = {}) {\n const conversationRef = useRef<Conversation | null>(null);\n const messageMapRef = useRef<Map<string, ConversationMessage>>(new Map());\n\n const [status, setStatus] = useState<ConversationStatus>(\"disconnected\");\n const [isSpeaking, setIsSpeaking] = useState(false);\n const [micMuted, setMicMutedState] = useState(false);\n const [messages, setMessages] = useState<ConversationMessage[]>([]);\n\n const startSession = useCallback(\n async (params: StartConversationOptions): Promise<string> => {\n if (conversationRef.current) {\n await conversationRef.current.endSession();\n conversationRef.current = null;\n }\n\n messageMapRef.current = new Map();\n setMessages([]);\n\n const conversation = await Conversation.startSession({\n ...params,\n textOnly: params.textOnly ?? options.textOnly,\n onConnect: () => {\n setStatus(\"connected\");\n options.onConnect?.();\n },\n onDisconnect: () => {\n setStatus(\"disconnected\");\n setIsSpeaking(false);\n options.onDisconnect?.();\n },\n onError: (error) => {\n options.onError?.(error);\n },\n onMessage: (message) => {\n messageMapRef.current.set(message.id, message);\n setMessages(\n Array.from(messageMapRef.current.values()).sort(\n (a, b) => a.timestamp - b.timestamp,\n ),\n );\n options.onMessage?.(message);\n },\n onStatusChange: (nextStatus) => {\n setStatus(nextStatus);\n options.onStatusChange?.(nextStatus);\n },\n onModeChange: (mode) => {\n setIsSpeaking(mode === \"speaking\");\n options.onModeChange?.(mode);\n },\n });\n\n conversationRef.current = conversation;\n setStatus(conversation.getStatus());\n setMicMutedState(conversation.getMicMuted());\n setIsSpeaking(conversation.getMode() === \"speaking\");\n\n return conversation.getId() ?? \"\";\n },\n [options],\n );\n\n const endSession = useCallback(async () => {\n if (!conversationRef.current) return;\n await conversationRef.current.endSession();\n conversationRef.current = null;\n setStatus(\"disconnected\");\n setIsSpeaking(false);\n }, []);\n\n const getId = useCallback(() => {\n return conversationRef.current?.getId();\n }, []);\n\n const getMessages = useCallback(() => {\n return conversationRef.current?.getMessages() ?? messages;\n }, [messages]);\n\n const setVolume = useCallback((volume: { volume: number }) => {\n conversationRef.current?.setVolume(volume);\n }, []);\n\n const setMicMuted = useCallback(async (isMuted: boolean) => {\n if (!conversationRef.current) return;\n await conversationRef.current.setMicMuted(isMuted);\n setMicMutedState(conversationRef.current.getMicMuted());\n }, []);\n\n const sendUserMessage = useCallback(async (text: string) => {\n if (!conversationRef.current) return;\n await conversationRef.current.sendUserMessage(text);\n }, []);\n\n const changeInputDevice = useCallback(async (config: InputDeviceConfig) => {\n if (!conversationRef.current) return false;\n return conversationRef.current.changeInputDevice(config);\n }, []);\n\n const changeOutputDevice = useCallback(async (config: OutputDeviceConfig) => {\n if (!conversationRef.current) return false;\n return conversationRef.current.changeOutputDevice(config);\n }, []);\n\n const getInputVolume = useCallback(() => {\n return conversationRef.current?.getInputVolume() ?? 0;\n }, []);\n\n const getOutputVolume = useCallback(() => {\n return conversationRef.current?.getOutputVolume() ?? 0;\n }, []);\n\n const getInputByteFrequencyData = useCallback(() => {\n return conversationRef.current?.getInputByteFrequencyData();\n }, []);\n\n const getOutputByteFrequencyData = useCallback(() => {\n return conversationRef.current?.getOutputByteFrequencyData();\n }, []);\n\n return useMemo(\n () => ({\n startSession,\n endSession,\n getId,\n getMessages,\n setVolume,\n setMicMuted,\n sendUserMessage,\n changeInputDevice,\n changeOutputDevice,\n getInputVolume,\n getOutputVolume,\n getInputByteFrequencyData,\n getOutputByteFrequencyData,\n messages,\n status,\n isSpeaking,\n micMuted,\n }),\n [\n startSession,\n endSession,\n getId,\n getMessages,\n setVolume,\n setMicMuted,\n sendUserMessage,\n changeInputDevice,\n changeOutputDevice,\n getInputVolume,\n getOutputVolume,\n getInputByteFrequencyData,\n getOutputByteFrequencyData,\n messages,\n status,\n isSpeaking,\n micMuted,\n ],\n );\n}\n\nexport type {\n ConversationMessage,\n ConversationMode,\n ConversationSource,\n ConversationStatus,\n InputDeviceConfig,\n OutputDeviceConfig,\n SetVolumeParams,\n};\n"],"names":["options","conversationRef","useRef","messageMapRef","Map","status","setStatus","useState","isSpeaking","setIsSpeaking","micMuted","setMicMutedState","messages","setMessages","startSession","useCallback","params","_temp2","_params$textOnly","current","Promise","resolve","Conversation","textOnly","onConnect","onDisconnect","onError","error","onMessage","message","set","id","Array","from","values","sort","a","b","timestamp","onStatusChange","nextStatus","onModeChange","mode","then","conversation","_conversation$getId","getStatus","getMicMuted","getMode","getId","_temp","endSession","e","reject","_conversationRef$curr","getMessages","_conversationRef$curr2","_conversationRef$curr3","setVolume","volume","_conversationRef$curr4","setMicMuted","isMuted","sendUserMessage","text","changeInputDevice","config","changeOutputDevice","getInputVolume","_conversationRef$curr5","_conversationRef$curr6","getOutputVolume","_conversationRef$curr7","_conversationRef$curr8","getInputByteFrequencyData","_conversationRef$curr9","getOutputByteFrequencyData","_conversationRef$curr0","useMemo"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vox-ai/react",
3
- "version": "0.3.2",
3
+ "version": "1.0.0",
4
4
  "description": "vox.ai React Library",
5
5
  "main": "./dist/lib.umd.js",
6
6
  "module": "./dist/lib.module.js",
@@ -30,12 +30,9 @@
30
30
  "test": "jest"
31
31
  },
32
32
  "dependencies": {
33
- "@livekit/components-react": "^2.9.0",
34
- "livekit-client": "^2.10.0"
33
+ "@vox-ai/client": "^0.1.0"
35
34
  },
36
35
  "peerDependencies": {
37
- "@livekit/components-react": "^2.9.0",
38
- "livekit-client": "^2.10.0",
39
36
  "react": ">=16.8.0",
40
37
  "react-dom": ">=16.8.0"
41
38
  },
@@ -1,95 +0,0 @@
1
- /**
2
- * VoxAgentState
3
- * @description The state of the agent
4
- */
5
- export type VoxAgentState = "disconnected" | "connecting" | "initializing" | "listening" | "thinking" | "speaking";
6
- /**
7
- * Function call related types
8
- */
9
- export interface FunctionToolsExecuted {
10
- type: "function_tools_executed";
11
- function_calls: FunctionCallInfo[];
12
- function_call_outputs: FunctionCallResult[];
13
- }
14
- export interface FunctionCallInfo {
15
- id: string;
16
- type: string;
17
- call_id: string;
18
- arguments: Record<string, any>;
19
- name: string;
20
- }
21
- export interface FunctionCallResult {
22
- id: string;
23
- name: string;
24
- type: string;
25
- call_id: string;
26
- output: string;
27
- is_error: boolean;
28
- }
29
- /**
30
- * VoxMessage
31
- * @description The message type between the agent and the user
32
- */
33
- export type VoxMessage = {
34
- id?: string;
35
- name: "agent" | "user" | "tool";
36
- message?: string;
37
- timestamp: number;
38
- isFinal?: boolean;
39
- tool?: FunctionToolsExecuted;
40
- };
41
- /**
42
- * VoxAIOptions
43
- * @description The callback functions for the useVoxAI hook
44
- */
45
- export interface VoxAIOptions {
46
- onConnect?: () => void;
47
- onDisconnect?: () => void;
48
- onError?: (error: Error) => void;
49
- onMessage?: (message: VoxMessage) => void;
50
- }
51
- /**
52
- * ConnectParams
53
- * @param agentId - The agent ID
54
- * @param agentVersion - The agent version, if not provided, the current version will be used
55
- * @param apiKey - The API key
56
- * @param dynamicVariables - The dynamic variables
57
- * @param metadata - 이 메타데이터는 아웃바운드 웹훅, 통화 기록에 포함됩니다.
58
- */
59
- export interface ConnectParams {
60
- agentId: string;
61
- agentVersion?: number;
62
- apiKey: string;
63
- dynamicVariables?: Record<string, any>;
64
- metadata?: Record<string, any>;
65
- }
66
- /**
67
- * useVoxAI
68
- * @description The hook for integrating with vox.ai voice assistant
69
- * @param options - The options for the useVoxAI hook
70
- * @returns The useVoxAI hook
71
- * @example
72
- * const { connect, disconnect, state, messages, send } = useVoxAI({
73
- * onConnect: () => console.log("Connected"),
74
- * onDisconnect: () => console.log("Disconnected"),
75
- * onError: (error) => console.error("Error:", error),
76
- * onMessage: (message) => console.log("Message:", message),
77
- * });
78
- */
79
- export declare function useVoxAI(options?: VoxAIOptions): {
80
- connect: ({ agentId, apiKey, dynamicVariables, metadata }: ConnectParams) => Promise<undefined>;
81
- disconnect: () => void;
82
- state: VoxAgentState;
83
- messages: VoxMessage[];
84
- send: ({ message, digit }: {
85
- message?: string;
86
- digit?: number;
87
- }) => void;
88
- audioWaveform: ({ speaker, barCount, updateInterval, }: {
89
- speaker?: "agent" | "user";
90
- barCount?: number;
91
- updateInterval?: number;
92
- }) => number[];
93
- toggleMic: (value: boolean) => void;
94
- setVolume: (volume: number) => void;
95
- };
@@ -1,2 +0,0 @@
1
- export declare const HTTPS_API_ORIGIN = "https://www.tryvox.co/api/agent/sdk";
2
- export declare const SDK_VERSION = "0.3.2";