ttp-agent-sdk 2.38.4 → 2.39.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.
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
- <title>TTP E-Commerce Widget - Test</title>
6
+ <title>TTP Hotels Flavor - Test</title>
7
7
  <style>
8
8
  body {
9
9
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
@@ -43,7 +43,7 @@
43
43
  .status.error { background: #FEE2E2; color: #991B1B; }
44
44
 
45
45
  button {
46
- background: #4F46E5;
46
+ background: #2563EB;
47
47
  color: white;
48
48
  border: none;
49
49
  padding: 12px 24px;
@@ -52,13 +52,11 @@
52
52
  font-size: 16px;
53
53
  margin: 10px 10px 10px 0;
54
54
  }
55
- button:hover { background: #4338CA; }
55
+ button:hover { background: #1D4ED8; }
56
56
  button.secondary { background: #6B7280; }
57
57
  button.secondary:hover { background: #4B5563; }
58
58
  button.success { background: #059669; }
59
59
  button.success:hover { background: #047857; }
60
- button.warning { background: #D97706; }
61
- button.warning:hover { background: #B45309; }
62
60
 
63
61
  label {
64
62
  display: flex;
@@ -68,7 +66,7 @@
68
66
  color: #374151;
69
67
  }
70
68
 
71
- select, input[type="text"], input[type="number"] {
69
+ select, input[type="text"] {
72
70
  padding: 8px 12px;
73
71
  border: 1px solid #D1D5DB;
74
72
  border-radius: 6px;
@@ -110,21 +108,6 @@
110
108
  color: #111827;
111
109
  }
112
110
 
113
- .cart-display {
114
- background: #F0FDF4;
115
- border: 1px solid #BBF7D0;
116
- border-radius: 8px;
117
- padding: 16px;
118
- margin: 16px 0;
119
- font-family: monospace;
120
- font-size: 13px;
121
- }
122
-
123
- .cart-display pre {
124
- margin: 0;
125
- white-space: pre-wrap;
126
- }
127
-
128
111
  @media (max-width: 768px) {
129
112
  body { margin: 0; padding: 10px; }
130
113
  .container { padding: 16px; border-radius: 8px; }
@@ -136,16 +119,16 @@
136
119
  </head>
137
120
  <body>
138
121
  <div class="container">
139
- <h1>🛒 TTP E-Commerce Widget Test</h1>
122
+ <h1>TTP Hotels Flavor Test</h1>
140
123
 
141
124
  <div class="info">
142
- <strong>What is TTPEcommerceWidget?</strong>
125
+ <strong>How it works:</strong>
143
126
  <ul>
144
- <li>Wraps the standard TTPChatWidget with an e-commerce layer</li>
145
- <li>Displays product cards when the agent sends <code>show_products</code> messages</li>
146
- <li>Manages a local cart with toast notifications and cart summary</li>
147
- <li>Supports partner integration via <code>addToCartFn</code> / <code>getCartFn</code> callbacks</li>
148
- <li>Test API available at <code>window.__TTP_ECOMMERCE__</code></li>
127
+ <li>Uses the standard <code>TTPChatWidget</code> with <code>flavor: { type: 'hotels', partnerId: 'mock-hotel' }</code></li>
128
+ <li>The backend injects hotel tools (<code>search_rooms</code>, <code>select_room</code>, <code>add_extra</code>, <code>get_booking</code>)</li>
129
+ <li>Room cards display when the agent sends <code>show_items</code> messages</li>
130
+ <li>Booking summary updates on <code>booking_updated</code> messages</li>
131
+ <li>Gallery (<code>show_media</code>) opens fullscreen with widget minimized</li>
149
132
  </ul>
150
133
  </div>
151
134
 
@@ -155,9 +138,7 @@
155
138
  <div class="settings-grid">
156
139
  <label>Agent
157
140
  <select id="agentSelect" onchange="handleAgentChange()">
158
- <option value="agent_e165840eb|app_wNGQKiMUfUT5JdVIaxzXOJfdcgBegxGY5hZo|en|ltr">e-commerce_english (agent_e165840eb)</option>
159
- <option value="agent_ed18369b3|app_wNGQKiMUfUT5JdVIaxzXOJfdcgBegxGY5hZo|he|rtl">e-commerce_hebrew (agent_ed18369b3)</option>
160
- <option value="agent_d119003d8|app_wNGQKiMUfUT5JdVIaxzXOJfdcgBegxGY5hZo|es|ltr">ecommerce_spanish (agent_d119003d8)</option>
141
+ <option value="agent_d0774f1af|app_wNGQKiMUfUT5JdVIaxzXOJfdcgBegxGY5hZo">Hotels Demo (agent_d0774f1af)</option>
161
142
  <option value="custom">Custom...</option>
162
143
  </select>
163
144
  </label>
@@ -199,66 +180,54 @@
199
180
  <button id="destroyBtn" class="secondary">Destroy Widget</button>
200
181
  </div>
201
182
 
202
- <h2>E-Commerce Test Actions</h2>
183
+ <h2>Test Actions (Simulated Messages)</h2>
203
184
 
204
185
  <div class="test-section">
205
- <h3>Show Products (simulated)</h3>
186
+ <h3>Show Rooms</h3>
206
187
  <p style="color: #6B7280; font-size: 14px; margin-bottom: 12px;">
207
- Injects a <code>show_products</code> message into the ecommerce layer — no voice call needed.
188
+ Injects a <code>show_items</code> message with mock hotel rooms — no voice call needed.
208
189
  </p>
209
- <div class="settings-grid">
210
- <label>Search Query
211
- <input id="productQuery" type="text" value="milk" />
212
- </label>
213
- <label>Layout
214
- <select id="productLayout">
215
- <option value="auto">Auto (cards &le;4, list 5+)</option>
216
- <option value="cards">Cards</option>
217
- <option value="list">List</option>
218
- </select>
219
- </label>
220
- </div>
221
- <button id="showProductsBtn" class="success">Show Products</button>
190
+ <button id="showRoomsBtn" class="success">Show Rooms</button>
222
191
  </div>
223
192
 
224
193
  <div class="test-section">
225
- <h3>Cart Updated (simulated)</h3>
194
+ <h3>Show Gallery</h3>
226
195
  <p style="color: #6B7280; font-size: 14px; margin-bottom: 12px;">
227
- Injects a <code>cart_updated</code> message to test toast and summary UI.
196
+ Injects a <code>show_media</code> message to test fullscreen gallery.
228
197
  </p>
229
- <button id="cartAddBtn" class="success">Simulate: Product Added</button>
230
- <button id="cartClearBtn" class="secondary">Clear Cart</button>
198
+ <button id="showGalleryBtn" class="success">Show Gallery</button>
231
199
  </div>
232
200
 
233
201
  <div class="test-section">
234
- <h3>Cart State</h3>
235
- <div id="cartDisplay" class="cart-display">
236
- <pre>No widget created yet</pre>
237
- </div>
238
- <button id="refreshCartBtn" class="secondary">Refresh Cart State</button>
202
+ <h3>Booking Updated</h3>
203
+ <p style="color: #6B7280; font-size: 14px; margin-bottom: 12px;">
204
+ Injects a <code>booking_updated</code> message to test the booking summary bar.
205
+ </p>
206
+ <button id="bookingBtn" class="success">Simulate Booking</button>
207
+ <button id="clearBookingBtn" class="secondary">Clear Booking</button>
239
208
  </div>
240
209
 
241
210
  <h2>Console Commands</h2>
242
- <div class="code-block">// Show products via test API (fetches from mock API)
243
- window.__TTP_ECOMMERCE__.showProducts('milk');
244
- window.__TTP_ECOMMERCE__.showProducts('bread', 3);
245
-
246
- // Inject raw messages
247
- window.__TTP_ECOMMERCE__.handleMessage({
248
- t: 'show_products',
249
- products: [
250
- { id: '1', name: 'Test Product', price: 9.99, image: '' }
211
+ <div class="code-block">// Access the widget instance
212
+ window.testWidget
213
+
214
+ // Inject messages manually via the flavor's messageHandlers
215
+ window.testWidget._flavor.messageHandlers['show_items']({
216
+ t: 'show_items',
217
+ items: [
218
+ { roomId: 'room-1', roomName: 'Test Room', imageUrl: '...', pricePerNight: 150, currency: 'USD', beds: 2, amenities: ['WiFi', 'Pool'] }
251
219
  ],
252
- title: 'Test Results'
220
+ title: 'Test Rooms'
253
221
  });
254
222
 
255
- // Cart operations
256
- window.__TTP_ECOMMERCE__.getCart();
257
- window.__TTP_ECOMMERCE__.clearCart();</div>
223
+ window.testWidget._flavor.messageHandlers['show_media']({
224
+ t: 'show_media',
225
+ images: [{ url: 'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=800', caption: 'Standard Room' }],
226
+ title: 'Hotel Photos'
227
+ });</div>
258
228
  </div>
259
229
 
260
230
  <script>
261
- // Load SDK - use fetch with ngrok-skip-browser-warning when on ngrok (fixes iPhone/mobile)
262
231
  (function() {
263
232
  var isNgrok = window.location.hostname.includes('ngrok');
264
233
  if (isNgrok) {
@@ -278,7 +247,7 @@ window.__TTP_ECOMMERCE__.clearCart();</div>
278
247
  </script>
279
248
 
280
249
  <script>
281
- let ecomWidget = null;
250
+ let chatWidget = null;
282
251
 
283
252
  function updateStatus(msg, type = '') {
284
253
  const el = document.getElementById('status');
@@ -286,27 +255,11 @@ window.__TTP_ECOMMERCE__.clearCart();</div>
286
255
  el.className = 'status ' + type;
287
256
  }
288
257
 
289
- function refreshCartDisplay() {
290
- const el = document.getElementById('cartDisplay');
291
- if (!window.__TTP_ECOMMERCE__) {
292
- el.innerHTML = '<pre>No widget created yet</pre>';
293
- return;
294
- }
295
- const cart = window.__TTP_ECOMMERCE__.getCart();
296
- el.innerHTML = '<pre>' + JSON.stringify(cart, null, 2) + '</pre>';
297
- }
298
-
299
258
  function handleAgentChange() {
300
259
  const sel = document.getElementById('agentSelect');
301
260
  const isCustom = sel.value === 'custom';
302
261
  document.getElementById('customAgentLabel').style.display = isCustom ? '' : 'none';
303
262
  document.getElementById('customAppLabel').style.display = isCustom ? '' : 'none';
304
-
305
- if (!isCustom) {
306
- const [, , lang, dir] = sel.value.split('|');
307
- document.getElementById('languageSelect').value = lang;
308
- document.getElementById('dirSelect').value = dir;
309
- }
310
263
  }
311
264
 
312
265
  function getAgentConfig() {
@@ -322,20 +275,20 @@ window.__TTP_ECOMMERCE__.clearCart();</div>
322
275
  }
323
276
 
324
277
  function createWidget() {
325
- if (ecomWidget) {
326
- ecomWidget.destroy();
327
- ecomWidget = null;
278
+ if (chatWidget) {
279
+ chatWidget.destroy();
280
+ chatWidget = null;
328
281
  }
329
282
 
330
283
  const TTPAgentSDK = window.TTPAgentSDK;
331
- if (!TTPAgentSDK || !TTPAgentSDK.TTPEcommerceWidget) {
332
- updateStatus('TTPEcommerceWidget not available in SDK', 'error');
284
+ if (!TTPAgentSDK || !TTPAgentSDK.TTPChatWidget) {
285
+ updateStatus('TTPChatWidget not available in SDK', 'error');
333
286
  return;
334
287
  }
335
288
 
336
289
  const agent = getAgentConfig();
337
290
 
338
- ecomWidget = new TTPAgentSDK.TTPEcommerceWidget({
291
+ chatWidget = new TTPAgentSDK.TTPChatWidget({
339
292
  agentId: agent.agentId,
340
293
  appId: agent.appId,
341
294
  language: document.getElementById('languageSelect').value,
@@ -344,102 +297,114 @@ window.__TTP_ECOMMERCE__.clearCart();</div>
344
297
  mode: document.getElementById('modeSelect').value,
345
298
  startOpen: document.getElementById('startOpenSelect').value === 'true'
346
299
  },
300
+ flavor: {
301
+ type: 'hotels',
302
+ partnerId: 'mock-hotel'
303
+ },
347
304
  icon: {
348
305
  type: 'custom',
349
306
  customImage: 'https://talktopc.com/logo192.png',
350
307
  size: 'medium',
351
308
  backgroundColor: '#FFFFFF'
352
- },
353
- partner: { name: 'TestStore' },
354
- cart: {
355
- addToCartFn: async (productId, qty) => {
356
- console.log('[TestPage] addToCartFn called:', productId, qty);
357
- return { ok: true };
358
- },
359
- getCartFn: async () => {
360
- console.log('[TestPage] getCartFn called');
361
- return window.__TTP_ECOMMERCE__?.getCart() || { items: [], total: 0, count: 0 };
362
- }
363
309
  }
364
310
  });
365
311
 
366
- window.testWidget = ecomWidget;
367
- updateStatus('TTPEcommerceWidget created successfully', 'success');
368
- refreshCartDisplay();
312
+ window.testWidget = chatWidget;
313
+ updateStatus('TTPChatWidget created with hotels flavor (partnerId: mock-hotel)', 'success');
369
314
  }
370
315
 
371
316
  // Button handlers
372
317
  document.getElementById('createBtn').onclick = createWidget;
373
318
 
374
319
  document.getElementById('destroyBtn').onclick = () => {
375
- if (ecomWidget) {
376
- ecomWidget.destroy();
377
- ecomWidget = null;
320
+ if (chatWidget) {
321
+ chatWidget.destroy();
322
+ chatWidget = null;
378
323
  updateStatus('Widget destroyed', '');
379
- refreshCartDisplay();
380
324
  }
381
325
  };
382
326
 
383
- document.getElementById('showProductsBtn').onclick = async () => {
384
- if (!window.__TTP_ECOMMERCE__) {
327
+ // Show Rooms inject mock show_items
328
+ document.getElementById('showRoomsBtn').onclick = () => {
329
+ if (!chatWidget || !chatWidget._flavor) {
385
330
  updateStatus('Create widget first', 'error');
386
331
  return;
387
332
  }
388
- const query = document.getElementById('productQuery').value || 'milk';
389
- try {
390
- await window.__TTP_ECOMMERCE__.showProducts(query);
391
- updateStatus('showProducts("' + query + '") sent', 'success');
392
- } catch (e) {
393
- updateStatus('showProducts failed: ' + e.message, 'error');
394
- }
333
+ chatWidget._flavor.messageHandlers['show_items']({
334
+ t: 'show_items',
335
+ items: [
336
+ { roomId: 'room-standard', roomName: 'Standard Room', imageUrl: 'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=400&h=300&fit=crop', pricePerNight: 120, currency: 'USD', beds: 1, amenities: ['WiFi', 'TV', 'Air Conditioning'], available: true },
337
+ { roomId: 'room-deluxe', roomName: 'Deluxe Room', imageUrl: 'https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=400&h=300&fit=crop', pricePerNight: 200, currency: 'USD', beds: 2, amenities: ['WiFi', 'TV', 'Pool', 'Mini Bar'], available: true },
338
+ { roomId: 'room-suite', roomName: 'Executive Suite', imageUrl: 'https://images.unsplash.com/photo-1566665797739-1674de7a421a?w=400&h=300&fit=crop', pricePerNight: 350, currency: 'USD', beds: 2, amenities: ['WiFi', 'TV', 'Pool', 'Spa', 'Balcony'], available: true },
339
+ { roomId: 'room-penthouse', roomName: 'Penthouse Suite', imageUrl: 'https://images.unsplash.com/photo-1578683010236-d716f9a3f461?w=400&h=300&fit=crop', pricePerNight: 600, currency: 'USD', beds: 3, amenities: ['WiFi', 'TV', 'Pool', 'Spa', 'Balcony', 'Butler'], available: true }
340
+ ],
341
+ title: '4 rooms available'
342
+ });
343
+ updateStatus('show_items injected with 4 rooms', 'success');
395
344
  };
396
345
 
397
- document.getElementById('cartAddBtn').onclick = async () => {
398
- if (!window.__TTP_ECOMMERCE__) {
346
+ // Show Gallery inject mock show_media
347
+ document.getElementById('showGalleryBtn').onclick = () => {
348
+ if (!chatWidget || !chatWidget._flavor) {
399
349
  updateStatus('Create widget first', 'error');
400
350
  return;
401
351
  }
402
- try {
403
- const baseUrl = window.__TTP_MOCK_API__ || 'https://backend.talktopc.com';
404
- const response = await fetch(`${baseUrl}/api/partner/mock-store/products/search?q=milk&limit=1&sessionId=test`);
405
- const data = await response.json();
406
- const product = data.products[0];
407
- window.__TTP_ECOMMERCE__.handleMessage({
408
- t: 'cart_updated',
409
- product: product,
410
- action: 'added',
411
- cartTotal: product.price,
412
- cartItemCount: 1
413
- });
414
- updateStatus('Simulated cart_updated for "' + product.name + '"', 'success');
415
- setTimeout(refreshCartDisplay, 200);
416
- } catch (e) {
417
- updateStatus('Failed to fetch product: ' + e.message, 'error');
418
- }
352
+ chatWidget._flavor.messageHandlers['show_media']({
353
+ t: 'show_media',
354
+ images: [
355
+ { url: 'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=800', caption: 'Standard Room' },
356
+ { url: 'https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=800', caption: 'Deluxe Room' },
357
+ { url: 'https://images.unsplash.com/photo-1566665797739-1674de7a421a?w=800', caption: 'Executive Suite' },
358
+ { url: 'https://images.unsplash.com/photo-1578683010236-d716f9a3f461?w=800', caption: 'Penthouse Suite' }
359
+ ],
360
+ title: 'Hotel Rooms'
361
+ });
362
+ updateStatus('show_media injected with 4 images (fullscreen gallery)', 'success');
419
363
  };
420
364
 
421
- document.getElementById('cartClearBtn').onclick = () => {
422
- if (!window.__TTP_ECOMMERCE__) {
365
+ // Booking Updated inject mock booking_updated
366
+ document.getElementById('bookingBtn').onclick = () => {
367
+ if (!chatWidget || !chatWidget._flavor) {
423
368
  updateStatus('Create widget first', 'error');
424
369
  return;
425
370
  }
426
- window.__TTP_ECOMMERCE__.clearCart();
427
- updateStatus('Cart cleared', '');
428
- refreshCartDisplay();
371
+ chatWidget._flavor.messageHandlers['booking_updated']({
372
+ t: 'booking_updated',
373
+ booking: {
374
+ roomId: 'room-deluxe',
375
+ roomName: 'Deluxe Room',
376
+ nights: 3,
377
+ guests: 2,
378
+ pricePerNight: 200,
379
+ totalPrice: 650,
380
+ currency: 'USD',
381
+ extras: [{ extraId: 'breakfast', name: 'Breakfast Buffet', price: 25, quantity: 1 }]
382
+ }
383
+ });
384
+ updateStatus('booking_updated injected (Deluxe Room, 3 nights, breakfast)', 'success');
429
385
  };
430
386
 
431
- document.getElementById('refreshCartBtn').onclick = refreshCartDisplay;
387
+ document.getElementById('clearBookingBtn').onclick = () => {
388
+ if (!chatWidget || !chatWidget._flavor) {
389
+ updateStatus('Create widget first', 'error');
390
+ return;
391
+ }
392
+ chatWidget._flavor.messageHandlers['booking_updated']({
393
+ t: 'booking_updated',
394
+ booking: {}
395
+ });
396
+ updateStatus('Booking cleared', '');
397
+ };
432
398
 
433
- // Wait for SDK and auto-create widget
399
+ // Wait for SDK and auto-create
434
400
  function waitForSDK() {
435
401
  return new Promise((resolve, reject) => {
436
- if (window.TTPAgentSDK?.TTPEcommerceWidget) { resolve(); return; }
402
+ if (window.TTPAgentSDK?.TTPChatWidget) { resolve(); return; }
437
403
  let attempts = 0;
438
- const maxAttempts = 150; // 15s - allows for slow mobile/ngrok
439
404
  const iv = setInterval(() => {
440
405
  attempts++;
441
- if (window.TTPAgentSDK?.TTPEcommerceWidget) { clearInterval(iv); resolve(); }
442
- else if (attempts >= maxAttempts) { clearInterval(iv); reject(new Error('SDK failed to load')); }
406
+ if (window.TTPAgentSDK?.TTPChatWidget) { clearInterval(iv); resolve(); }
407
+ else if (attempts >= 150) { clearInterval(iv); reject(new Error('SDK failed to load')); }
443
408
  }, 100);
444
409
  });
445
410
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ttp-agent-sdk",
3
- "version": "2.38.4",
3
+ "version": "2.39.0",
4
4
  "description": "Comprehensive Voice Agent SDK with Customizable Widget - Real-time audio, WebSocket communication, React components, and extensive customization options",
5
5
  "main": "dist/agent-widget.js",
6
6
  "module": "dist/agent-widget.esm.js",