@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-sdkQuick 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:
- Start with REST API calls to
/integrations/sync/v1/messagefor bot interactions - Switch to SDK WebSocket connection when a live agent connects
- 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
sourcemust be set tosyncApito 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 thehistory:previousMessagesevent 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+
