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

wiil-web

v0.0.2

Published

Browser SDK for WIIL Platform - OTT chat and voice widget integration

Readme

wiil-web

Browser SDK for the WIIL Platform. Build custom chat and voice experiences with real-time WebSocket messaging and WebRTC-powered voice calls.

Installation

npm install wiil-web

Quick Start

import { WiilClient, RouteService } from 'wiil-web';

const client = new WiilClient({
  configId: 'your-config-id',
  routeService: RouteService.NA,
});

// Set contact info (optional)
client.setContactInfo({ email: '[email protected]' });

// Connect to chat
await client.connectChat();

// Listen for messages
client.chat.on('messageChunk', ({ chunk }) => {
  console.log('Streaming:', chunk);
});

client.chat.on('messageComplete', ({ content }) => {
  console.log('Complete:', content);
});

// Send a message
await client.chat.sendMessage('Hello!');

// Cleanup
await client.destroy();

Features

  • Chat Client - Real-time WebSocket messaging with streaming support
  • Voice Client - WebRTC integration for voice calls
  • Message Queue - Offline message buffering with automatic retry
  • Auto-Reconnect - Exponential backoff reconnection handling
  • Type Safety - Full TypeScript support with Zod runtime validation
  • Event-Driven - Typed event system with unsubscribe support

API Reference

WiilClient

Main entry point for the SDK. Provides unified access to chat and voice functionality.

import { WiilClient, RouteService } from 'wiil-web';

const client = new WiilClient({
  configId: 'your-config-id',   // Required
  routeService: RouteService.NA, // Required - RouteService.NA or RouteService.EU
  debug: false,                 // Optional - enable console logging
  chat: {                       // Optional - ChatClient options
    autoReconnect: true,
    maxReconnectAttempts: 5,
    reconnectDelay: 1000,
    maxQueueSize: 50,
    messageExpiryMs: 300000,
  },
});

WiilClient Methods

| Method | Description | | -------- | ----------- | | connectChat() | Fetches chat config and connects to WebSocket | | disconnectChat() | Disconnects from chat | | connectVoice() | Fetches voice config and connects to voice channel | | disconnectVoice() | Disconnects from voice | | setContactInfo(contact) | Sets contact info for API requests | | getContactInfo() | Returns current contact info | | getConnectionStates() | Returns chat and voice connection states | | getIsOnline() | Returns network online status | | on(event, listener) | Registers event listener (returns unsubscribe fn) | | off(event, listener) | Removes event listener | | destroy() | Cleans up all resources |

WiilClient Properties

| Property | Description | | ---------- | ----------- | | chat | ChatClient instance (throws if not connected) | | voice | VoiceClient instance (throws if not connected) | | hasChatClient | Returns true if chat client exists | | hasVoiceClient | Returns true if voice client exists |

WiilClient Events

| Event | Payload | Description | | ------- | --------- | ----------- | | chat:stateChanged | { previous, current } | Chat connection state changed | | voice:stateChanged | { previous, current } | Voice connection state changed | | network:online | void | Network came online | | network:offline | void | Network went offline |

ChatClient

WebSocket chat client with message queue and auto-reconnect.

const chat = client.chat;

// Listen for streaming chunks
chat.on('messageChunk', ({ chunk, conversationId, streamId }) => {
  appendToUI(chunk);
});

// Listen for complete messages
chat.on('messageComplete', ({ content, conversationId }) => {
  finalizeMessage(content);
});

// Send message (queued if offline)
const messageId = await chat.sendMessage('Hello!');

// Send typing indicator
chat.sendTypingIndicator(true);

ChatClient Methods

| Method | Description | | -------- | ----------- | | connect(config) | Connects to WebSocket | | disconnect(clearQueue?) | Disconnects (optionally clears queue) | | sendMessage(content) | Sends message, returns message ID | | sendTypingIndicator(isTyping) | Sends typing indicator | | getState() | Returns connection state | | isConnected() | Returns true if connected | | getConversationId() | Returns current conversation ID | | getMessageQueue() | Returns queued messages | | getQueueSize() | Returns pending queue size | | clearQueue() | Clears message queue | | reconnect() | Manually triggers reconnection | | on(event, listener) | Registers event listener | | off(event, listener) | Removes event listener | | destroy() | Cleans up resources |

ChatClient Events

| Event | Payload | Description | | ------- | --------- | ----------- | | connecting | void | Connection starting | | connected | void | Successfully connected | | disconnected | { code, reason } | Disconnected from server | | reconnecting | { attempt, maxAttempts } | Reconnection attempt starting | | reconnected | void | Successfully reconnected | | reconnectFailed | { error } | All reconnection attempts failed | | message | OttIncomingMessage | Raw incoming message | | messageChunk | { chunk, conversationId?, streamId?, timestamp? } | Streaming content chunk | | messageComplete | { conversationId?, content?, timestamp? } | Message streaming complete | | thinking | { isThinking } | Assistant thinking state | | processing | { isProcessing } | Assistant processing state | | messageSent | { conversationId, messageId? } | Message sent successfully | | messageQueued | { message } | Message queued (offline) | | queueProcessed | { sent, expired, failed } | Queue processing complete | | error | Error | Error occurred |

Options

| Option | Type | Default | Description | | -------- | ------ | --------- | ----------- | | autoReconnect | boolean | true | Auto-reconnect on disconnect | | maxReconnectAttempts | number | 5 | Max reconnection attempts | | reconnectDelay | number | 1000 | Base reconnect delay (ms) | | maxQueueSize | number | 50 | Max queued messages | | messageExpiryMs | number | 300000 | Message expiry time (5 min) |

VoiceClient

WebRTC client for voice calls.

const voice = client.voice;

// Listen for connection
voice.on('connected', () => {
  console.log('Voice connected');
});

// Listen for remote audio
voice.on('remoteAudioStarted', ({ user }) => {
  console.log('Agent speaking:', user.uid);
});

// Start recording
await voice.startRecording();

// Stop recording
await voice.stopRecording();

VoiceClient Methods

| Method | Description | | -------- | ----------- | | connect(config) | Connects to voice channel | | disconnect() | Disconnects from channel | | startRecording() | Starts microphone and publishes | | stopRecording() | Stops microphone and unpublishes | | getState() | Returns connection state | | isConnected() | Returns true if connected | | isRecording() | Returns true if recording | | on(event, listener) | Registers event listener | | off(event, listener) | Removes event listener | | destroy() | Cleans up resources |

VoiceClient Events

| Event | Payload | Description | | ------- | --------- | ----------- | | connecting | void | Connection starting | | connected | void | Successfully connected | | disconnected | void | Disconnected from channel | | recordingStarted | void | Microphone recording started | | recordingStopped | void | Microphone recording stopped | | remoteAudioStarted | { user: { uid } } | Remote user started audio | | remoteAudioStopped | { user: { uid } } | Remote user stopped audio | | connectionStateChanged | { current, previous } | Connection state changed | | error | Error | Error occurred |

RouteService

Select the route service based on your platform's registered business region:

  • RouteService.EU - Use if your business is registered in Europe
  • RouteService.NA - Default for all other regions
import { RouteService } from 'wiil-web';

// RouteService values
RouteService.NA  // 'north-america' (default)
RouteService.EU  // 'europe'

Connection States

import { ConnectionState } from 'wiil-web';

// ConnectionState values
ConnectionState.DISCONNECTED  // 'disconnected'
ConnectionState.CONNECTING    // 'connecting'
ConnectionState.CONNECTED     // 'connected'
ConnectionState.ERROR         // 'error'

Voice Connection States

import { VoiceConnectionState } from 'wiil-web';

// VoiceConnectionState values
VoiceConnectionState.DISCONNECTED  // 'disconnected'
VoiceConnectionState.CONNECTING    // 'connecting'
VoiceConnectionState.CONNECTED     // 'connected'
VoiceConnectionState.RECORDING     // 'recording'
VoiceConnectionState.ERROR         // 'error'

Examples

Detailed Example Guides

The complete, split walkthroughs are available in examples/basic-usage:

Chat with Message Queue

import { WiilClient, RouteService } from 'wiil-web';

const client = new WiilClient({
  configId: 'config-123',
  routeService: RouteService.NA,
  chat: {
    autoReconnect: true,
    maxQueueSize: 100,
    messageExpiryMs: 600000, // 10 minutes
  },
});

// Track queued messages
client.chat.on('messageQueued', ({ message }) => {
  showPendingIndicator(message.id);
});

// Track sent messages
client.chat.on('messageSent', ({ messageId }) => {
  markAsSent(messageId);
});

// Track queue processing
client.chat.on('queueProcessed', ({ sent, expired, failed }) => {
  console.log(`Processed: ${sent} sent, ${expired} expired, ${failed} failed`);
});

await client.connectChat();

// Messages queue automatically if disconnected
await client.chat.sendMessage('This will queue if offline');

Voice Call

import { WiilClient, RouteService } from 'wiil-web';

const client = new WiilClient({
  configId: 'config-123',
  routeService: RouteService.NA,
});

// Listen for remote audio
client.on('voice:stateChanged', ({ current }) => {
  updateVoiceUI(current);
});

await client.connectVoice();

client.voice.on('remoteAudioStarted', () => {
  showSpeakingIndicator();
});

// Start talking
await client.voice.startRecording();

// Stop talking
await client.voice.stopRecording();

// End call
await client.disconnectVoice();

Network Awareness

import { WiilClient, RouteService } from 'wiil-web';

const client = new WiilClient({ configId: 'config-123', routeService: RouteService.NA });

client.on('network:offline', () => {
  showOfflineBanner();
});

client.on('network:online', () => {
  hideOfflineBanner();
  // Chat will auto-reconnect and process queued messages
});

// Check network status
if (client.getIsOnline()) {
  await client.connectChat();
}

Handling Reconnection

import { WiilClient, RouteService } from 'wiil-web';

const client = new WiilClient({
  configId: 'config-123',
  routeService: RouteService.NA,
  chat: {
    autoReconnect: true,
    maxReconnectAttempts: 10,
    reconnectDelay: 2000,
  },
});

await client.connectChat();

client.chat.on('reconnecting', ({ attempt, maxAttempts }) => {
  showReconnectingUI(`Attempt ${attempt}/${maxAttempts}`);
});

client.chat.on('reconnected', () => {
  hideReconnectingUI();
  showSuccessToast('Reconnected!');
});

client.chat.on('reconnectFailed', ({ error }) => {
  showErrorUI(error.message);
  showManualReconnectButton();
});

Types

All types are exported for TypeScript users:

import { RouteService } from 'wiil-web';

import type {
  // Client options
  WiilClientOptions,
  WiilClientFullOptions,
  ChatClientOptions,
  ContactInfo,

  // Connection states
  ConnectionState,
  ConnectionStates,
  VoiceConnectionState,

  // Events
  WiilClientEventType,
  WiilClientEventMap,
  ChatEventType,
  ChatEventMap,
  VoiceEventType,
  VoiceEventMap,

  // Messages
  QueuedMessage,
  QueuedMessageStatus,
  MessageChunkPayload,
  MessageCompletePayload,

  // OTT types
  OttIncomingMessage,
  OttChatConfig,
  OttVoiceConfig,
} from 'wiil-web';

Browser Support

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

Requires:

  • fetch API
  • WebSocket API
  • navigator.mediaDevices (for voice)

License

MIT