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

@yellowdotai/yellow-chat-sdk

v1.0.4

Published

Yellow Chat SDK - A TypeScript SDK for Yellow.ai chat integration

Downloads

495

Readme

Yellow Chat SDK

A TypeScript SDK for integrating Yellow.ai chat functionality into web applications. This SDK provides event-based communication for a clean separation between the data layer and UI layer.

Installation

npm install @yellowdotai/yellow-chat-sdk

Quick Start

import { YellowChat } from '@yellowdotai/yellow-chat-sdk';

// Create SDK instance
const sdk = new YellowChat();

// Subscribe to events BEFORE connecting
sdk.on('connection:connected', ({ userId }) => {
  console.log('Connected as:', userId);
});

sdk.on('message:received', (message) => {
  console.log('New message:', message);
  // message.type = 'text' | 'image' | 'video' | 'audio' | 'file' | 'location' | 'system'
  // message.content = { message: "..." } for text, { url: "..." } for media
  // Render message in your UI based on type
});

sdk.on('agent:assigned', (agentProfile) => {
  // Update UI to show agent info
  console.log('Agent joined:', agentProfile.name);
});

sdk.on('agent:left', () => {
  // Agent has left the conversation
  console.log('Agent left the conversation');
});

// Initialize and connect
await sdk.init({
  bot: 'your-bot-id',
  host: 'https://cloud.yellow.ai'
});

await sdk.connect();

// Send messages
await sdk.sendMessage('Hello!');

Configuration

interface SDKConfig {
  // Required
  bot: string;                    // Your bot ID

  // Server
  host?: string;                  // API host URL (default: 'https://cloud.yellow.ai')

  // Message Source (IMPORTANT for live agent integrations)
  source?: string;                // 'yellowmessenger' (default) or 'syncApi'

  // User
  userId?: string;                // User ID (auto-generated if not provided)
  name?: string;                  // User display name

  // Authentication
  ymAuthenticationToken?: string; // Auth token (if required by your bot)

  // Custom Payload
  payload?: Record<string, unknown>;

  // Journey Triggers
  triggerJourney?: string;

  // UTM Parameters
  utmSource?: string;
  utmCampaign?: string;
  utmMedium?: string;

  // Debug
  debug?: boolean;                // Enable debug logging
}

Source Configuration

The source parameter is critical when integrating with live agent functionality:

| Source | Use Case | Description | |--------|----------|-------------| | yellowmessenger | Fully Headless | Default. Use when SDK is your only communication channel. All messages sent/received via WebSocket. | | syncApi | Hybrid Mode (REST + SDK) | Use when integrating with /integrations/sync/v1/message REST API. Required for hybrid architectures. |

When to use yellowmessenger (default)

Use this for a fully headless approach where the SDK handles all communication:

await sdk.init({
  bot: 'your-bot-id',
  source: 'yellowmessenger'  // or omit - this is the default
});

await sdk.connect(userId);

// All communication via SDK
await sdk.sendMessage('Hello');

When to use syncApi

Use this for a hybrid approach where you:

  1. Start with REST API calls to /integrations/sync/v1/message for bot interactions
  2. Switch to SDK WebSocket connection when a live agent connects
  3. Continue using SDK for real-time agent communication
// Step 1: Initially use REST API for bot messages
const response = await fetch('/integrations/sync/v1/message', {
  method: 'POST',
  body: JSON.stringify({
    botId: 'your-bot-id',
    sender: senderId,
    data: { message: 'Hello' }
  })
});

// Step 2: When live agent connects, switch to SDK with syncApi source
if (response.data.includes('live agent connected')) {
  await sdk.init({
    bot: 'your-bot-id',
    source: 'syncApi'  // IMPORTANT: Must match REST API source for ticket consistency
  });
  
  await sdk.connect(senderId);  // Use same senderId from REST API
  
  // Now receive agent messages via SDK events
  sdk.on('message:received', (msg) => console.log('Agent:', msg));
}

Important: When using hybrid mode, the source must be set to syncApi to maintain ticket consistency between REST API and WebSocket channels. Using mismatched sources will cause live agent tickets to close unexpectedly.

API

Lifecycle

// Initialize
await sdk.init(config);

// Connect (optionally with a specific user ID)
await sdk.connect(userId?);

// Disconnect
sdk.disconnect();

Messaging

// Send text message
await sdk.sendMessage('Hello!');

// Send file
await sdk.sendFile(file);

Note: Message history is automatically fetched when you call connect(). Listen to the history:previousMessages event to receive it.

State

// Check connection
const connected = sdk.isConnected();

// Get user ID
const userId = sdk.getUserId();

// Get bot info
const botInfo = sdk.getBotInfo();

Events

// Subscribe to events (returns unsubscribe function)
const unsubscribe = sdk.on('message:received', (message) => {
  console.log(message);
});

// Unsubscribe later
unsubscribe();

// Or use off()
sdk.off('message:received', handler);

Events

Connection Events

| Event | Payload | Description | |-------|---------|-------------| | connection:connecting | - | Connection attempt started | | connection:connected | { userId } | Successfully connected | | connection:disconnected | { code, message, wasClean } | Disconnected | | connection:reconnecting | { attempt, delay } | Reconnecting | | connection:reconnected | { userId } | Successfully reconnected | | connection:error | SDKError | Connection error |

Message Events

| Event | Payload | Description | |-------|---------|-------------| | message:received | IncomingMessage | Message from bot/agent | | message:sent | { id, message } | Message sent successfully | | message:failed | { messageId, error } | Message failed to send |

Agent Events

| Event | Payload | Description | |-------|---------|-------------| | agent:assigned | AgentProfile | Live agent joined the conversation | | agent:left | - | Agent left or ticket closed/resolved | | agent:typing | boolean | Agent is typing |

Ticket Events

| Event | Payload | Description | |-------|---------|-------------| | ticket:closed | - | Ticket has been closed | | ticket:resolved | - | Ticket has been resolved |

History Events

| Event | Payload | Description | |-------|---------|-------------| | history:previousMessages | Message[] | Previous conversation messages (auto-fetched on connect) |

History is automatically fetched when connect() is called. On reconnection, only missed messages are fetched.

Network Events

| Event | Payload | Description | |-------|---------|-------------| | network:online | - | Network connection restored | | network:offline | - | Network connection lost |

Integration Modes

Mode 1: Fully Headless (SDK Only)

Use the SDK as your only communication channel. Best for custom chat widgets.

import { YellowChat } from 'yellow-chat-sdk';

const sdk = new YellowChat();

sdk.on('message:received', (message) => {
  console.log('Message:', message);
});

await sdk.init({
  bot: 'your-bot-id',
  source: 'yellowmessenger'  // Default - can be omitted
});

await sdk.connect();
await sdk.sendMessage('Hello');

Mode 2: Hybrid Mode (REST API + SDK)

Start with REST API for bot interactions, switch to SDK when live agent connects.

Why use Hybrid Mode?

  • Server-side control over bot conversations
  • Reduced client-side complexity for bot-only flows
  • Real-time WebSocket only when needed (live agent)
import { YellowChat } from 'yellow-chat-sdk';

let chatMode = 'rest';
let sdk = null;
const senderId = 'unique-user-id';

// REST API for bot messages
async function sendMessageViaREST(message) {
  const response = await fetch('https://cloud.yellow.ai/integrations/sync/v1/message', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': 'your-api-key'
    },
    body: JSON.stringify({
      botId: 'your-bot-id',
      sender: senderId,
      data: { message }
    })
  });
  
  const data = await response.json();
  
  // Check if live agent connected
  if (data.data?.messageArray?.some(m => 
    m.message?.toLowerCase().includes('live agent') && 
    m.message?.toLowerCase().includes('connected')
  )) {
    await switchToWebSocketMode();
  }
  
  return data;
}

// Switch to SDK when live agent connects
async function switchToWebSocketMode() {
  sdk = new YellowChat();
  
  sdk.on('message:received', (message) => {
    console.log('Agent message:', message);
  });
  
  sdk.on('ticket:closed', () => {
    console.log('Ticket closed - switching back to REST');
    chatMode = 'rest';
  });
  
  sdk.on('ticket:resolved', () => {
    console.log('Ticket resolved - switching back to REST');
    chatMode = 'rest';
  });
  
  await sdk.init({
    bot: 'your-bot-id',
    source: 'syncApi'  // CRITICAL: Must be 'syncApi' for hybrid mode!
  });
  
  await sdk.connect(senderId);  // Use same senderId from REST API
  chatMode = 'websocket';
}

// Send message based on current mode
async function sendMessage(message) {
  if (chatMode === 'rest') {
    return sendMessageViaREST(message);
  } else {
    return sdk.sendMessage(message);
  }
}

Critical: When using hybrid mode, you MUST set source: 'syncApi' in the SDK configuration. This ensures that messages sent via the SDK are correctly associated with tickets created via the REST API. Using mismatched sources will cause tickets to close unexpectedly.

Message Types

All messages from the SDK follow a standardized, flattened format:

interface IncomingMessage {
  id: string;                                    // Unique message ID
  timestamp: Date;                               // Message timestamp
  type: MessageType;                             // Message type
  content: MessageContent;                       // Flattened content
  sender: 'bot' | 'agent' | 'user' | 'system';  // Who sent the message
}

// Message types
type MessageType = 'text' | 'image' | 'video' | 'audio' | 'file' | 'location' | 'system' | 'cards' | 'quickReplies';

// Content is FLATTENED based on type:
// Text:     { message: "Hello" }
// Image:    { url: "https://..." }
// Video:    { url: "https://...", controls: true, autoplay: false, ... }
// Audio:    { url: "https://..." }
// File:     { url: "https://...", name: "document.pdf" }
// Location: { latitude: 12.34, longitude: 56.78 }
// System:   { message: "Agent joined the conversation" }

Example: Handling Different Message Types

sdk.on('message:received', (message) => {
  switch (message.type) {
    case 'text':
      console.log('Text:', message.content.message);
      break;
    case 'image':
      console.log('Image URL:', message.content.url);
      break;
    case 'video':
      console.log('Video URL:', message.content.url);
      // Optional: message.content.controls, message.content.autoplay
      break;
    case 'file':
      console.log('File:', message.content.name, message.content.url);
      break;
    case 'system':
      console.log('System:', message.content.message);
      // e.g., "Agent joined the conversation", "Conversation ended"
      break;
  }
});

Error Handling

import { YellowChatError } from 'yellow-chat-sdk';

try {
  await sdk.sendMessage('Hello');
} catch (error) {
  if (error instanceof YellowChatError) {
    console.error('SDK Error:', error.code, error.message);
    if (error.recoverable) {
      // Retry logic
    }
  }
}

// Or listen for error events
sdk.on('connection:error', (error) => {
  console.error('Connection error:', error);
});

sdk.on('message:failed', ({ messageId, error }) => {
  console.error('Message failed:', messageId, error);
});

TypeScript

The SDK is written in TypeScript and includes full type definitions.

import type {
  SDKConfig,
  IncomingMessage,
  AgentProfile,
  SDKEvents,
  SDKEventName
} from 'yellow-chat-sdk';

Browser Support

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