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 🙏

© 2025 – Pkg Stats / Ryan Hefner

targetai-client-js-sdk

v1.0.5

Published

JavaScript SDK for TargetAI WebRTC voice agent communication

Readme

TargetAI JavaScript SDK

A JavaScript SDK for connecting to TargetAI voice agents via WebRTC, similar to the Retell client SDK.

Installation

npm install targetai-client-js-sdk

Quick Start

import { TargetAIWebClient } from 'targetai-client-js-sdk';

// Create client instance with token authentication
const client = new TargetAIWebClient({
  serverUrl: 'https://your-runtime-server.com',      // Runtime server (/run/voice/offer)
  tokenServerUrl: 'https://your-token-server.com',   // Token server (/token)
});

// Set up event listeners
client.on('call_started', () => {
  console.log('Call started');
});

client.on('call_ended', () => {
  console.log('Call ended');
});

client.on('update', (message) => {
  console.log('Received message:', message);
});

client.on('error', (error) => {
  console.error('Error:', error);
});

// Start a call (automatically gets token and authenticates)
await client.startCall({
  agentUuid: 'your-agent-uuid',
  allowedResponses: ['text', 'voice']
});

// Send a message
client.sendMessage('Hello, agent!');

// Stop the call
client.stopCall();

Token Authentication Flow

The SDK uses token-based authentication similar to the frontend negotiation pattern:

  1. Token Request: Browser → Token Server (/token) → Get Token
  2. WebRTC Offer: Browser → Runtime Server (/run/voice/offer) with Token → WebRTC Connection
  3. Auto-Retry: If 401 response, automatically retries with new token

API Reference

Constructor

const client = new TargetAIWebClient(config);

Config Options:

  • serverUrl (string, required): Your TargetAI runtime server URL (where /run/voice/offer endpoint is)
  • tokenServerUrl (string, optional): Token server URL (where /token endpoint is). Defaults to serverUrl
  • apiKey (string, optional): API key for token generation
  • iceServers (RTCIceServer[], optional): Custom ICE servers for WebRTC
  • audioConstraints (object, optional): Audio input constraints

Methods

startCall(options)

Starts a voice call with the agent.

Options:

  • agentUuid (string, required): The UUID of the agent to connect to
  • dataInput (object, optional): Initial data to pass to the agent
  • messages (Message[], optional): Initial conversation messages
  • allowedResponses (string[], optional): Array of allowed response types: ['text', 'voice']
  • sampleRate (number, optional): Audio sample rate (default: 24000)
  • captureDeviceId (string, optional): Microphone device ID
  • playbackDeviceId (string, optional): Speaker device ID
  • emitRawAudioSamples (boolean, optional): Whether to emit raw audio data
await client.startCall({
  agentUuid: 'agent-123',
  allowedResponses: ['text', 'voice'],
  sampleRate: 24000,
  emitRawAudioSamples: true
});

stopCall()

Stops the current call and cleans up resources.

sendMessage(message)

Sends a text message to the agent.

Parameters:

  • message (string): The message to send

Returns: boolean - True if message was sent successfully

destroy()

Completely destroys the client instance and cleans up all resources.

Events

call_started

Fired when the call begins successfully.

call_ended

Fired when the call ends.

agent_start_talking

Fired when the agent starts speaking.

agent_stop_talking

Fired when the agent stops speaking.

update

Fired when a new message is received from the agent.

Parameters:

  • message (Message): The processed message object

audio

Fired when raw audio data is available (if emitRawAudioSamples is enabled).

Parameters:

  • audioData (Float32Array): Raw PCM audio data

error

Fired when an error occurs.

Parameters:

  • error (Error): The error object

connection_state_change

Fired when the WebRTC connection state changes.

Parameters:

  • state (RTCPeerConnectionState): The new connection state

Message Types

The SDK handles various message types from the agent:

  • user: Messages from the user (speech recognition)
  • assistant: Agent responses
  • tool: Tool/function calls
  • tool_response: Tool/function responses
  • system: System messages
  • error: Error messages
  • completion: Task completion notifications

Audio Utilities

The SDK includes audio utility functions:

import { 
  convertUnsigned8ToFloat32, 
  convertFloat32ToUnsigned8,
  getAudioInputDevices,
  getAudioOutputDevices 
} from 'targetai-client-js-sdk';

// Get available audio devices
const inputDevices = await getAudioInputDevices();
const outputDevices = await getAudioOutputDevices();

// Convert audio formats
const float32Audio = convertUnsigned8ToFloat32(uint8Array);
const uint8Audio = convertFloat32ToUnsigned8(float32Array);

Browser Compatibility

  • Chrome 60+
  • Firefox 55+
  • Safari 11+
  • Edge 79+

Requires WebRTC support and microphone permissions.

Error Handling

client.on('error', (error) => {
  console.error('SDK Error:', error.message);
  
  // Handle specific error types
  if (error.message.includes('microphone')) {
    // Handle microphone permission error
  } else if (error.message.includes('negotiation')) {
    // Handle WebRTC negotiation error
  }
});

Example: Complete Voice Chat

<!DOCTYPE html>
<html>
<head>
    <title>TargetAI Voice Chat</title>
</head>
<body>
    <button id="startCall">Start Call</button>
    <button id="stopCall" disabled>Stop Call</button>
    <input type="text" id="messageInput" placeholder="Type a message..." disabled>
    <button id="sendMessage" disabled>Send</button>
    <div id="messages"></div>

    <script type="module">
        import { TargetAIWebClient } from './dist/index.esm.js';

        const client = new TargetAIWebClient({
            serverUrl: 'https://your-server.com'
        });

        const startBtn = document.getElementById('startCall');
        const stopBtn = document.getElementById('stopCall');
        const messageInput = document.getElementById('messageInput');
        const sendBtn = document.getElementById('sendMessage');
        const messagesDiv = document.getElementById('messages');

        // Event listeners
        client.on('call_started', () => {
            startBtn.disabled = true;
            stopBtn.disabled = false;
            messageInput.disabled = false;
            sendBtn.disabled = false;
            addMessage('System: Call started');
        });

        client.on('call_ended', () => {
            startBtn.disabled = false;
            stopBtn.disabled = true;
            messageInput.disabled = true;
            sendBtn.disabled = true;
            addMessage('System: Call ended');
        });

        client.on('update', (message) => {
            addMessage(`${message.type}: ${message.content || JSON.stringify(message)}`);
        });

        client.on('error', (error) => {
            addMessage(`Error: ${error.message}`);
        });

        // UI event handlers
        startBtn.onclick = async () => {
            try {
                await client.startCall({
                    agentUuid: 'your-agent-uuid',
                    allowedResponses: ['text', 'voice']
                });
            } catch (error) {
                alert('Failed to start call: ' + error.message);
            }
        };

        stopBtn.onclick = () => {
            client.stopCall();
        };

        sendBtn.onclick = () => {
            const message = messageInput.value.trim();
            if (message) {
                client.sendMessage(message);
                addMessage(`You: ${message}`);
                messageInput.value = '';
            }
        };

        messageInput.onkeypress = (e) => {
            if (e.key === 'Enter') {
                sendBtn.click();
            }
        };

        function addMessage(text) {
            const div = document.createElement('div');
            div.textContent = `${new Date().toLocaleTimeString()}: ${text}`;
            messagesDiv.appendChild(div);
            messagesDiv.scrollTop = messagesDiv.scrollHeight;
        }
    </script>
</body>
</html>

Building the SDK

# Install dependencies
npm install

# Build the SDK
npm run build

# Run tests
npm test

License

ISC