@vocobase/voice-client-sdk
v1.0.3
Published
Voice AI agent SDK for Revenue Generator platform
Downloads
13
Maintainers
Readme
Voice Client SDK
Voice AI agent SDK for the Revenue Generator platform.
Changelog
v1.0.1 (Security Patch)
- Fixed: Race condition in reconnection logic that could cause duplicate sessions
- Fixed: API key format warning now only logs in debug mode (was exposing info in production)
- Fixed:
onDisconnectcallback now fires even when disconnect encounters an error - Added: Debug logging for cleanup operations
- Added: XSS security documentation for transcript content
v1.0.0 (Production Ready)
- Added:
useNetworkStatus()hook for online/offline detection - Added: Configurable transcript size limits (
transcript.maxEntries) - Added: Debug mode with detailed logging (
debug: true) - Added: Expanded SDK configuration with nested options
- Added: Full TypeScript types for all config options
v0.3.0
- Added: Automatic reconnection on connection loss (up to 3 attempts by default)
- Added:
onReconnectingandonReconnectedcallbacks - Added:
isReconnecting,reconnectAttempt,maxReconnectAttemptsinuseConnectionState() - Added:
maxReconnectAttemptsprop forVoiceSessionProvider - Added: Automatic retry with exponential backoff for transient API failures
- Added: New connection states:
reconnecting,disconnected
v0.2.0
- Breaking: Fixed authentication header format (now uses
Authorization: Bearerinstead ofx-api-key) - Added: Input validation with clear error messages for invalid API keys and agent names
- Added: 30-second request timeout to prevent hanging requests
- Removed:
useVoiceVisualizerhook (incomplete implementation). Use the<VoiceVisualizer>component instead.
Installation
npm install voice-client-sdk
# or
pnpm add voice-client-sdk
# or
yarn add voice-client-sdkQuick Start
Using the Styled Component
The easiest way to add voice capabilities:
import { VoiceAgent } from 'voice-client-sdk';
import 'voice-client-sdk/styles.css';
function App() {
return (
<VoiceAgent
apiKey="rg_live_xxx"
agentName="my-sales-agent"
onConnect={() => console.log('Connected!')}
onTranscript={(entry) => console.log(entry)}
onError={(error) => console.error(error)}
/>
);
}Using Headless Hooks
For custom UI implementations:
import {
VoiceSessionProvider,
useVoiceSession,
useConnectionState,
useTranscript,
} from 'voice-client-sdk';
function App() {
return (
<VoiceSessionProvider apiKey="rg_live_xxx" agentName="my-agent">
<CustomVoiceUI />
</VoiceSessionProvider>
);
}
function CustomVoiceUI() {
const { connect, disconnect } = useVoiceSession();
const { isConnected, isConnecting } = useConnectionState();
const { entries } = useTranscript();
return (
<div>
{!isConnected ? (
<button onClick={connect} disabled={isConnecting}>
{isConnecting ? 'Connecting...' : 'Start'}
</button>
) : (
<>
<button onClick={disconnect}>End</button>
<ul>
{entries.map((entry, i) => (
<li key={i}>
<strong>{entry.role}:</strong> {entry.content}
</li>
))}
</ul>
</>
)}
</div>
);
}API Reference
Components
<VoiceAgent />
Drop-in voice agent component with built-in UI.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| apiKey | string | required | Your API key |
| agentName | string | required | Name of the agent |
| visualizer | VisualizerOptions | - | Customize the visualizer |
| onConnect | () => void | - | Called when connected |
| onDisconnect | () => void | - | Called when disconnected |
| onError | (error: VoiceAgentError) => void | - | Called on error |
| onTranscript | (entry: TranscriptEntry) => void | - | Called per message |
| onSessionEnd | (data: SessionEndData) => void | - | Called when session ends |
| onReconnecting | (attempt, max) => void | - | Called on reconnection attempt |
| onReconnected | () => void | - | Called after successful reconnection |
| connectLabel | string | "Start Conversation" | Connect button text |
| connectingLabel | string | "Connecting..." | Connecting button text |
| disconnectLabel | string | "End" | Disconnect button text |
Hooks
useVoiceSession()
const { connect, disconnect, sessionId, error } = useVoiceSession();useConnectionState()
const {
state, // Current ConnectionState
isConnected, // true when connected
isConnecting, // true when connecting
isReconnecting, // true when attempting to reconnect
isDisconnected, // true when idle, disconnected, or error
reconnectAttempt, // Current reconnection attempt (0 if not reconnecting)
maxReconnectAttempts, // Maximum reconnection attempts allowed
} = useConnectionState();useTranscript()
const { entries, latestEntry, count, isEmpty } = useTranscript();useNetworkStatus()
Monitor browser online/offline status.
const { isOnline, lastChanged } = useNetworkStatus();
if (!isOnline) {
return <div>You are offline. Please check your connection.</div>;
}Types
interface TranscriptEntry {
role: 'user' | 'bot';
content: string;
timestamp: string;
latency_ms?: number;
}
interface SessionEndData {
sessionId: string;
durationSeconds: number;
transcript: TranscriptEntry[];
latencySummary: { min_ms: number; max_ms: number; avg_ms: number };
creditsUsed: number;
}
type ConnectionState =
| 'idle' // Initial state, ready to connect
| 'connecting' // Establishing connection
| 'connected' // Active session
| 'reconnecting' // Attempting to restore lost connection
| 'disconnecting' // Graceful disconnect in progress
| 'disconnected' // Clean disconnect (can reconnect)
| 'error'; // Fatal error (cannot recover)
interface VoiceAgentError {
code: VoiceAgentErrorCode;
message: string;
}
type VoiceAgentErrorCode =
| 'MIC_PERMISSION_DENIED'
| 'INVALID_API_KEY'
| 'INSUFFICIENT_CREDITS'
| 'CONCURRENCY_LIMIT'
| 'AGENT_NOT_FOUND'
| 'NETWORK_ERROR'
| 'CONNECTION_FAILED'
| 'PIPECAT_ERROR';Configuration
Setting the Backend URL
By default, the SDK connects to the production API. For development:
import { setConfig } from 'voice-client-sdk';
// Set custom backend URL (for development)
setConfig({ baseUrl: 'http://localhost:3001' });Or use environment variables:
# Next.js
NEXT_PUBLIC_VOICE_API_URL=http://localhost:3001Full Configuration Options
import { setConfig } from 'voice-client-sdk';
setConfig({
// Backend API URL
baseUrl: 'http://localhost:3001',
// Retry behavior for API calls
retry: {
maxAttempts: 3, // Number of retry attempts
baseDelayMs: 1000, // Initial delay between retries
maxDelayMs: 10000, // Maximum delay (with exponential backoff)
},
// Connection behavior
connection: {
timeoutMs: 30000, // Request timeout
reconnectAttempts: 3, // WebRTC reconnection attempts
},
// Transcript management
transcript: {
maxEntries: 100, // Limit transcript size (null = unlimited)
},
// Enable debug logging
debug: true,
});Debug Mode
Enable detailed logging to troubleshoot issues:
setConfig({ debug: true });
// Console output:
// [VoiceSDK 2024-01-15T10:30:00.000Z] Starting connection
// [VoiceSDK 2024-01-15T10:30:00.100Z] Microphone permission granted
// [VoiceSDK 2024-01-15T10:30:00.500Z] Session started { sessionId: "..." }
// [VoiceSDK 2024-01-15T10:30:01.000Z] Connection establishedReconnection Behavior
The SDK automatically handles connection drops and attempts to reconnect:
<VoiceSessionProvider
apiKey="rg_live_xxx"
agentName="my-agent"
maxReconnectAttempts={3} // Default: 3
onReconnecting={(attempt, max) => {
console.log(`Reconnecting... attempt ${attempt} of ${max}`);
}}
onReconnected={() => {
console.log('Successfully reconnected!');
}}
>
<MyVoiceUI />
</VoiceSessionProvider>Reconnection behavior:
- Triggered automatically on unexpected disconnects
- Uses exponential backoff (1s, 2s, 4s, ...)
- Preserves transcript and session state during reconnection
- Fires
onErrorwithCONNECTION_FAILEDif all attempts fail - Does NOT trigger on intentional
disconnect()calls
Error Handling
<VoiceAgent
apiKey="..."
agentName="..."
onError={(error) => {
switch (error.code) {
case 'MIC_PERMISSION_DENIED':
// Show permission instructions
break;
case 'INSUFFICIENT_CREDITS':
// Prompt to add credits
break;
case 'CONCURRENCY_LIMIT':
// Show "try again later" message
break;
case 'CONNECTION_FAILED':
// Connection lost and couldn't reconnect
break;
default:
// Generic error handling
}
}}
/>License
MIT
