npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vocobase/voice-client-sdk

v1.0.3

Published

Voice AI agent SDK for Revenue Generator platform

Downloads

13

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: onDisconnect callback 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: onReconnecting and onReconnected callbacks
  • Added: isReconnecting, reconnectAttempt, maxReconnectAttempts in useConnectionState()
  • Added: maxReconnectAttempts prop for VoiceSessionProvider
  • 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: Bearer instead of x-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: useVoiceVisualizer hook (incomplete implementation). Use the <VoiceVisualizer> component instead.

Installation

npm install voice-client-sdk
# or
pnpm add voice-client-sdk
# or
yarn add voice-client-sdk

Quick 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:3001

Full 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 established

Reconnection 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 onError with CONNECTION_FAILED if 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