@yellowdotai/yellow-chat-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,462 @@
1
+ # Yellow Chat SDK
2
+
3
+ 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.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @yellowdotai/yellow-chat-sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { YellowChat } from '@yellowdotai/yellow-chat-sdk';
15
+
16
+ // Create SDK instance
17
+ const sdk = new YellowChat();
18
+
19
+ // Subscribe to events BEFORE connecting
20
+ sdk.on('connection:connected', ({ userId }) => {
21
+ console.log('Connected as:', userId);
22
+ });
23
+
24
+ sdk.on('message:received', (message) => {
25
+ console.log('New message:', message);
26
+ // message.type = 'text' | 'image' | 'video' | 'audio' | 'file' | 'location' | 'system'
27
+ // message.content = { message: "..." } for text, { url: "..." } for media
28
+ // Render message in your UI based on type
29
+ });
30
+
31
+ sdk.on('agent:assigned', (agentProfile) => {
32
+ // Update UI to show agent info
33
+ console.log('Agent joined:', agentProfile.name);
34
+ });
35
+
36
+ sdk.on('agent:left', () => {
37
+ // Agent has left the conversation
38
+ console.log('Agent left the conversation');
39
+ });
40
+
41
+ // Initialize and connect
42
+ await sdk.init({
43
+ bot: 'your-bot-id',
44
+ host: 'https://cloud.yellow.ai'
45
+ });
46
+
47
+ await sdk.connect();
48
+
49
+ // Send messages
50
+ await sdk.sendMessage('Hello!');
51
+ ```
52
+
53
+ ## Configuration
54
+
55
+ ```typescript
56
+ interface SDKConfig {
57
+ // Required
58
+ bot: string; // Your bot ID
59
+
60
+ // Server
61
+ host?: string; // API host URL (default: 'https://cloud.yellow.ai')
62
+
63
+ // Message Source (IMPORTANT for live agent integrations)
64
+ source?: string; // 'yellowmessenger' (default) or 'syncApi'
65
+
66
+ // User
67
+ userId?: string; // User ID (auto-generated if not provided)
68
+ name?: string; // User display name
69
+
70
+ // Authentication
71
+ ymAuthenticationToken?: string; // Auth token (if required by your bot)
72
+
73
+ // Custom Payload
74
+ payload?: Record<string, unknown>;
75
+
76
+ // Journey Triggers
77
+ triggerJourney?: string;
78
+
79
+ // UTM Parameters
80
+ utmSource?: string;
81
+ utmCampaign?: string;
82
+ utmMedium?: string;
83
+
84
+ // Debug
85
+ debug?: boolean; // Enable debug logging
86
+ }
87
+ ```
88
+
89
+ ### Source Configuration
90
+
91
+ The `source` parameter is critical when integrating with live agent functionality:
92
+
93
+ | Source | Use Case | Description |
94
+ |--------|----------|-------------|
95
+ | `yellowmessenger` | **Fully Headless** | Default. Use when SDK is your only communication channel. All messages sent/received via WebSocket. |
96
+ | `syncApi` | **Hybrid Mode (REST + SDK)** | Use when integrating with `/integrations/sync/v1/message` REST API. Required for hybrid architectures. |
97
+
98
+ #### When to use `yellowmessenger` (default)
99
+
100
+ Use this for a **fully headless** approach where the SDK handles all communication:
101
+
102
+ ```typescript
103
+ await sdk.init({
104
+ bot: 'your-bot-id',
105
+ source: 'yellowmessenger' // or omit - this is the default
106
+ });
107
+
108
+ await sdk.connect(userId);
109
+
110
+ // All communication via SDK
111
+ await sdk.sendMessage('Hello');
112
+ ```
113
+
114
+ #### When to use `syncApi`
115
+
116
+ Use this for a **hybrid approach** where you:
117
+ 1. Start with REST API calls to `/integrations/sync/v1/message` for bot interactions
118
+ 2. Switch to SDK WebSocket connection when a live agent connects
119
+ 3. Continue using SDK for real-time agent communication
120
+
121
+ ```typescript
122
+ // Step 1: Initially use REST API for bot messages
123
+ const response = await fetch('/integrations/sync/v1/message', {
124
+ method: 'POST',
125
+ body: JSON.stringify({
126
+ botId: 'your-bot-id',
127
+ sender: senderId,
128
+ data: { message: 'Hello' }
129
+ })
130
+ });
131
+
132
+ // Step 2: When live agent connects, switch to SDK with syncApi source
133
+ if (response.data.includes('live agent connected')) {
134
+ await sdk.init({
135
+ bot: 'your-bot-id',
136
+ source: 'syncApi' // IMPORTANT: Must match REST API source for ticket consistency
137
+ });
138
+
139
+ await sdk.connect(senderId); // Use same senderId from REST API
140
+
141
+ // Now receive agent messages via SDK events
142
+ sdk.on('message:received', (msg) => console.log('Agent:', msg));
143
+ }
144
+ ```
145
+
146
+ > **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.
147
+
148
+ ## API
149
+
150
+ ### Lifecycle
151
+
152
+ ```typescript
153
+ // Initialize
154
+ await sdk.init(config);
155
+
156
+ // Connect (optionally with a specific user ID)
157
+ await sdk.connect(userId?);
158
+
159
+ // Disconnect
160
+ sdk.disconnect();
161
+ ```
162
+
163
+ ### Messaging
164
+
165
+ ```typescript
166
+ // Send text message
167
+ await sdk.sendMessage('Hello!');
168
+
169
+ // Send file
170
+ await sdk.sendFile(file);
171
+ ```
172
+
173
+ > **Note:** Message history is **automatically fetched** when you call `connect()`. Listen to the `history:previousMessages` event to receive it.
174
+
175
+ ### State
176
+
177
+ ```typescript
178
+ // Check connection
179
+ const connected = sdk.isConnected();
180
+
181
+ // Get user ID
182
+ const userId = sdk.getUserId();
183
+
184
+ // Get bot info
185
+ const botInfo = sdk.getBotInfo();
186
+ ```
187
+
188
+ ### Events
189
+
190
+ ```typescript
191
+ // Subscribe to events (returns unsubscribe function)
192
+ const unsubscribe = sdk.on('message:received', (message) => {
193
+ console.log(message);
194
+ });
195
+
196
+ // Unsubscribe later
197
+ unsubscribe();
198
+
199
+ // Or use off()
200
+ sdk.off('message:received', handler);
201
+ ```
202
+
203
+ ## Events
204
+
205
+ ### Connection Events
206
+
207
+ | Event | Payload | Description |
208
+ |-------|---------|-------------|
209
+ | `connection:connecting` | - | Connection attempt started |
210
+ | `connection:connected` | `{ userId }` | Successfully connected |
211
+ | `connection:disconnected` | `{ code, message, wasClean }` | Disconnected |
212
+ | `connection:reconnecting` | `{ attempt, delay }` | Reconnecting |
213
+ | `connection:reconnected` | `{ userId }` | Successfully reconnected |
214
+ | `connection:error` | `SDKError` | Connection error |
215
+
216
+ ### Message Events
217
+
218
+ | Event | Payload | Description |
219
+ |-------|---------|-------------|
220
+ | `message:received` | `IncomingMessage` | Message from bot/agent |
221
+ | `message:sent` | `{ id, message }` | Message sent successfully |
222
+ | `message:failed` | `{ messageId, error }` | Message failed to send |
223
+
224
+ ### Agent Events
225
+
226
+ | Event | Payload | Description |
227
+ |-------|---------|-------------|
228
+ | `agent:assigned` | `AgentProfile` | Live agent joined the conversation |
229
+ | `agent:left` | - | Agent left or ticket closed/resolved |
230
+ | `agent:typing` | `boolean` | Agent is typing |
231
+
232
+ ### Ticket Events
233
+
234
+ | Event | Payload | Description |
235
+ |-------|---------|-------------|
236
+ | `ticket:closed` | - | Ticket has been closed |
237
+ | `ticket:resolved` | - | Ticket has been resolved |
238
+
239
+ ### History Events
240
+
241
+ | Event | Payload | Description |
242
+ |-------|---------|-------------|
243
+ | `history:previousMessages` | `Message[]` | Previous conversation messages (auto-fetched on connect) |
244
+
245
+ > History is automatically fetched when `connect()` is called. On reconnection, only missed messages are fetched.
246
+
247
+ ### Network Events
248
+
249
+ | Event | Payload | Description |
250
+ |-------|---------|-------------|
251
+ | `network:online` | - | Network connection restored |
252
+ | `network:offline` | - | Network connection lost |
253
+
254
+ ## Integration Modes
255
+
256
+ ### Mode 1: Fully Headless (SDK Only)
257
+
258
+ Use the SDK as your only communication channel. Best for custom chat widgets.
259
+
260
+ ```typescript
261
+ import { YellowChat } from 'yellow-chat-sdk';
262
+
263
+ const sdk = new YellowChat();
264
+
265
+ sdk.on('message:received', (message) => {
266
+ console.log('Message:', message);
267
+ });
268
+
269
+ await sdk.init({
270
+ bot: 'your-bot-id',
271
+ source: 'yellowmessenger' // Default - can be omitted
272
+ });
273
+
274
+ await sdk.connect();
275
+ await sdk.sendMessage('Hello');
276
+ ```
277
+
278
+ ### Mode 2: Hybrid Mode (REST API + SDK)
279
+
280
+ Start with REST API for bot interactions, switch to SDK when live agent connects.
281
+
282
+ **Why use Hybrid Mode?**
283
+ - Server-side control over bot conversations
284
+ - Reduced client-side complexity for bot-only flows
285
+ - Real-time WebSocket only when needed (live agent)
286
+
287
+ ```typescript
288
+ import { YellowChat } from 'yellow-chat-sdk';
289
+
290
+ let chatMode = 'rest';
291
+ let sdk = null;
292
+ const senderId = 'unique-user-id';
293
+
294
+ // REST API for bot messages
295
+ async function sendMessageViaREST(message) {
296
+ const response = await fetch('https://cloud.yellow.ai/integrations/sync/v1/message', {
297
+ method: 'POST',
298
+ headers: {
299
+ 'Content-Type': 'application/json',
300
+ 'x-api-key': 'your-api-key'
301
+ },
302
+ body: JSON.stringify({
303
+ botId: 'your-bot-id',
304
+ sender: senderId,
305
+ data: { message }
306
+ })
307
+ });
308
+
309
+ const data = await response.json();
310
+
311
+ // Check if live agent connected
312
+ if (data.data?.messageArray?.some(m =>
313
+ m.message?.toLowerCase().includes('live agent') &&
314
+ m.message?.toLowerCase().includes('connected')
315
+ )) {
316
+ await switchToWebSocketMode();
317
+ }
318
+
319
+ return data;
320
+ }
321
+
322
+ // Switch to SDK when live agent connects
323
+ async function switchToWebSocketMode() {
324
+ sdk = new YellowChat();
325
+
326
+ sdk.on('message:received', (message) => {
327
+ console.log('Agent message:', message);
328
+ });
329
+
330
+ sdk.on('ticket:closed', () => {
331
+ console.log('Ticket closed - switching back to REST');
332
+ chatMode = 'rest';
333
+ });
334
+
335
+ sdk.on('ticket:resolved', () => {
336
+ console.log('Ticket resolved - switching back to REST');
337
+ chatMode = 'rest';
338
+ });
339
+
340
+ await sdk.init({
341
+ bot: 'your-bot-id',
342
+ source: 'syncApi' // CRITICAL: Must be 'syncApi' for hybrid mode!
343
+ });
344
+
345
+ await sdk.connect(senderId); // Use same senderId from REST API
346
+ chatMode = 'websocket';
347
+ }
348
+
349
+ // Send message based on current mode
350
+ async function sendMessage(message) {
351
+ if (chatMode === 'rest') {
352
+ return sendMessageViaREST(message);
353
+ } else {
354
+ return sdk.sendMessage(message);
355
+ }
356
+ }
357
+ ```
358
+
359
+ > **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.
360
+
361
+ ## Message Types
362
+
363
+ All messages from the SDK follow a **standardized, flattened format**:
364
+
365
+ ```typescript
366
+ interface IncomingMessage {
367
+ id: string; // Unique message ID
368
+ timestamp: Date; // Message timestamp
369
+ type: MessageType; // Message type
370
+ content: MessageContent; // Flattened content
371
+ sender: 'bot' | 'agent' | 'user' | 'system'; // Who sent the message
372
+ }
373
+
374
+ // Message types
375
+ type MessageType = 'text' | 'image' | 'video' | 'audio' | 'file' | 'location' | 'system' | 'cards' | 'quickReplies';
376
+
377
+ // Content is FLATTENED based on type:
378
+ // Text: { message: "Hello" }
379
+ // Image: { url: "https://..." }
380
+ // Video: { url: "https://...", controls: true, autoplay: false, ... }
381
+ // Audio: { url: "https://..." }
382
+ // File: { url: "https://...", name: "document.pdf" }
383
+ // Location: { latitude: 12.34, longitude: 56.78 }
384
+ // System: { message: "Agent joined the conversation" }
385
+ ```
386
+
387
+ ### Example: Handling Different Message Types
388
+
389
+ ```typescript
390
+ sdk.on('message:received', (message) => {
391
+ switch (message.type) {
392
+ case 'text':
393
+ console.log('Text:', message.content.message);
394
+ break;
395
+ case 'image':
396
+ console.log('Image URL:', message.content.url);
397
+ break;
398
+ case 'video':
399
+ console.log('Video URL:', message.content.url);
400
+ // Optional: message.content.controls, message.content.autoplay
401
+ break;
402
+ case 'file':
403
+ console.log('File:', message.content.name, message.content.url);
404
+ break;
405
+ case 'system':
406
+ console.log('System:', message.content.message);
407
+ // e.g., "Agent joined the conversation", "Conversation ended"
408
+ break;
409
+ }
410
+ });
411
+ ```
412
+
413
+ ## Error Handling
414
+
415
+ ```typescript
416
+ import { YellowChatError } from 'yellow-chat-sdk';
417
+
418
+ try {
419
+ await sdk.sendMessage('Hello');
420
+ } catch (error) {
421
+ if (error instanceof YellowChatError) {
422
+ console.error('SDK Error:', error.code, error.message);
423
+ if (error.recoverable) {
424
+ // Retry logic
425
+ }
426
+ }
427
+ }
428
+
429
+ // Or listen for error events
430
+ sdk.on('connection:error', (error) => {
431
+ console.error('Connection error:', error);
432
+ });
433
+
434
+ sdk.on('message:failed', ({ messageId, error }) => {
435
+ console.error('Message failed:', messageId, error);
436
+ });
437
+ ```
438
+
439
+ ## TypeScript
440
+
441
+ The SDK is written in TypeScript and includes full type definitions.
442
+
443
+ ```typescript
444
+ import type {
445
+ SDKConfig,
446
+ IncomingMessage,
447
+ AgentProfile,
448
+ SDKEvents,
449
+ SDKEventName
450
+ } from 'yellow-chat-sdk';
451
+ ```
452
+
453
+ ## Browser Support
454
+
455
+ - Chrome 60+
456
+ - Firefox 55+
457
+ - Safari 11+
458
+ - Edge 79+
459
+
460
+ ## License
461
+
462
+ MIT