targetai-client-js-sdk
v1.0.5
Published
JavaScript SDK for TargetAI WebRTC voice agent communication
Maintainers
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-sdkQuick 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:
- Token Request: Browser → Token Server (
/token) → Get Token - WebRTC Offer: Browser → Runtime Server (
/run/voice/offer) with Token → WebRTC Connection - 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/offerendpoint is)tokenServerUrl(string, optional): Token server URL (where/tokenendpoint is). Defaults toserverUrlapiKey(string, optional): API key for token generationiceServers(RTCIceServer[], optional): Custom ICE servers for WebRTCaudioConstraints(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 todataInput(object, optional): Initial data to pass to the agentmessages(Message[], optional): Initial conversation messagesallowedResponses(string[], optional): Array of allowed response types:['text', 'voice']sampleRate(number, optional): Audio sample rate (default: 24000)captureDeviceId(string, optional): Microphone device IDplaybackDeviceId(string, optional): Speaker device IDemitRawAudioSamples(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 responsestool: Tool/function callstool_response: Tool/function responsessystem: System messageserror: Error messagescompletion: 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 testLicense
ISC
