ttp-agent-sdk 2.34.9 → 2.34.12

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.
@@ -0,0 +1,436 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
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>
7
+ <style>
8
+ body {
9
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
10
+ max-width: 1200px;
11
+ margin: 40px auto;
12
+ padding: 20px;
13
+ background: #F9FAFB;
14
+ }
15
+
16
+ .container {
17
+ background: white;
18
+ padding: 30px;
19
+ border-radius: 12px;
20
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
21
+ }
22
+
23
+ h1 { color: #111827; margin-top: 0; }
24
+ h2 { color: #374151; border-bottom: 2px solid #E5E7EB; padding-bottom: 8px; margin-top: 30px; }
25
+
26
+ .info {
27
+ background: #EFF6FF;
28
+ border-left: 4px solid #3B82F6;
29
+ padding: 16px;
30
+ margin: 20px 0;
31
+ border-radius: 4px;
32
+ }
33
+
34
+ .status {
35
+ margin: 20px 0;
36
+ padding: 12px;
37
+ background: #F3F4F6;
38
+ border-radius: 6px;
39
+ font-family: monospace;
40
+ font-size: 14px;
41
+ }
42
+ .status.success { background: #D1FAE5; color: #065F46; }
43
+ .status.error { background: #FEE2E2; color: #991B1B; }
44
+
45
+ button {
46
+ background: #4F46E5;
47
+ color: white;
48
+ border: none;
49
+ padding: 12px 24px;
50
+ border-radius: 6px;
51
+ cursor: pointer;
52
+ font-size: 16px;
53
+ margin: 10px 10px 10px 0;
54
+ }
55
+ button:hover { background: #4338CA; }
56
+ button.secondary { background: #6B7280; }
57
+ button.secondary:hover { background: #4B5563; }
58
+ button.success { background: #059669; }
59
+ button.success:hover { background: #047857; }
60
+ button.warning { background: #D97706; }
61
+ button.warning:hover { background: #B45309; }
62
+
63
+ label {
64
+ display: flex;
65
+ flex-direction: column;
66
+ gap: 4px;
67
+ font-size: 14px;
68
+ color: #374151;
69
+ }
70
+
71
+ select, input[type="text"], input[type="number"] {
72
+ padding: 8px 12px;
73
+ border: 1px solid #D1D5DB;
74
+ border-radius: 6px;
75
+ font-size: 14px;
76
+ font-family: inherit;
77
+ background: white;
78
+ color: #111827;
79
+ }
80
+
81
+ .code-block {
82
+ background: #1F2937;
83
+ color: #F9FAFB;
84
+ padding: 16px;
85
+ border-radius: 6px;
86
+ font-family: monospace;
87
+ font-size: 12px;
88
+ overflow-x: auto;
89
+ margin: 20px 0;
90
+ white-space: pre-wrap;
91
+ }
92
+
93
+ .settings-grid {
94
+ display: grid;
95
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
96
+ gap: 16px;
97
+ margin: 16px 0;
98
+ }
99
+
100
+ .test-section {
101
+ border: 1px solid #E5E7EB;
102
+ border-radius: 8px;
103
+ padding: 20px;
104
+ margin: 16px 0;
105
+ background: #F9FAFB;
106
+ }
107
+
108
+ .test-section h3 {
109
+ margin: 0 0 12px 0;
110
+ color: #111827;
111
+ }
112
+
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
+ @media (max-width: 768px) {
129
+ body { margin: 0; padding: 10px; }
130
+ .container { padding: 16px; border-radius: 8px; }
131
+ h1 { font-size: 24px; }
132
+ button { width: 100%; margin: 8px 0; }
133
+ .settings-grid { grid-template-columns: 1fr; }
134
+ }
135
+ </style>
136
+ </head>
137
+ <body>
138
+ <div class="container">
139
+ <h1>🛒 TTP E-Commerce Widget Test</h1>
140
+
141
+ <div class="info">
142
+ <strong>What is TTPEcommerceWidget?</strong>
143
+ <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>
149
+ </ul>
150
+ </div>
151
+
152
+ <div id="status" class="status">Loading SDK...</div>
153
+
154
+ <h2>Widget Configuration</h2>
155
+ <div class="settings-grid">
156
+ <label>Agent
157
+ <select id="agentSelect" onchange="handleAgentChange()">
158
+ <option value="agent_87c4a55a1|app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC|en|ltr">e-commerce_english (agent_87c4a55a1)</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>
161
+ <option value="custom">Custom...</option>
162
+ </select>
163
+ </label>
164
+ <label id="customAgentLabel" style="display:none">Agent ID
165
+ <input id="customAgentId" type="text" placeholder="agent_..." />
166
+ </label>
167
+ <label id="customAppLabel" style="display:none">App ID
168
+ <input id="customAppId" type="text" placeholder="app_..." />
169
+ </label>
170
+ <label>Language
171
+ <select id="languageSelect">
172
+ <option value="en" selected>English</option>
173
+ <option value="he">Hebrew</option>
174
+ </select>
175
+ </label>
176
+ <label>Direction
177
+ <select id="dirSelect">
178
+ <option value="ltr" selected>LTR</option>
179
+ <option value="rtl">RTL</option>
180
+ </select>
181
+ </label>
182
+ <label>Widget Mode
183
+ <select id="modeSelect">
184
+ <option value="unified" selected>Unified (Both)</option>
185
+ <option value="voice-only">Voice Only</option>
186
+ <option value="text-only">Text Only</option>
187
+ </select>
188
+ </label>
189
+ <label>Start Open
190
+ <select id="startOpenSelect">
191
+ <option value="true" selected>Yes</option>
192
+ <option value="false">No</option>
193
+ </select>
194
+ </label>
195
+ </div>
196
+
197
+ <div style="margin-top: 16px;">
198
+ <button id="createBtn">Create Widget</button>
199
+ <button id="destroyBtn" class="secondary">Destroy Widget</button>
200
+ </div>
201
+
202
+ <h2>E-Commerce Test Actions</h2>
203
+
204
+ <div class="test-section">
205
+ <h3>Show Products (simulated)</h3>
206
+ <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.
208
+ </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>
222
+ </div>
223
+
224
+ <div class="test-section">
225
+ <h3>Cart Updated (simulated)</h3>
226
+ <p style="color: #6B7280; font-size: 14px; margin-bottom: 12px;">
227
+ Injects a <code>cart_updated</code> message to test toast and summary UI.
228
+ </p>
229
+ <button id="cartAddBtn" class="success">Simulate: Product Added</button>
230
+ <button id="cartClearBtn" class="secondary">Clear Cart</button>
231
+ </div>
232
+
233
+ <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>
239
+ </div>
240
+
241
+ <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: '' }
251
+ ],
252
+ title: 'Test Results'
253
+ });
254
+
255
+ // Cart operations
256
+ window.__TTP_ECOMMERCE__.getCart();
257
+ window.__TTP_ECOMMERCE__.clearCart();</div>
258
+ </div>
259
+
260
+ <script src="/dist/agent-widget.js"></script>
261
+
262
+ <script>
263
+ let ecomWidget = null;
264
+
265
+ function updateStatus(msg, type = '') {
266
+ const el = document.getElementById('status');
267
+ el.textContent = msg;
268
+ el.className = 'status ' + type;
269
+ }
270
+
271
+ function refreshCartDisplay() {
272
+ const el = document.getElementById('cartDisplay');
273
+ if (!window.__TTP_ECOMMERCE__) {
274
+ el.innerHTML = '<pre>No widget created yet</pre>';
275
+ return;
276
+ }
277
+ const cart = window.__TTP_ECOMMERCE__.getCart();
278
+ el.innerHTML = '<pre>' + JSON.stringify(cart, null, 2) + '</pre>';
279
+ }
280
+
281
+ function handleAgentChange() {
282
+ const sel = document.getElementById('agentSelect');
283
+ const isCustom = sel.value === 'custom';
284
+ document.getElementById('customAgentLabel').style.display = isCustom ? '' : 'none';
285
+ document.getElementById('customAppLabel').style.display = isCustom ? '' : 'none';
286
+
287
+ if (!isCustom) {
288
+ const [, , lang, dir] = sel.value.split('|');
289
+ document.getElementById('languageSelect').value = lang;
290
+ document.getElementById('dirSelect').value = dir;
291
+ }
292
+ }
293
+
294
+ function getAgentConfig() {
295
+ const sel = document.getElementById('agentSelect');
296
+ if (sel.value === 'custom') {
297
+ return {
298
+ agentId: document.getElementById('customAgentId').value,
299
+ appId: document.getElementById('customAppId').value
300
+ };
301
+ }
302
+ const [agentId, appId] = sel.value.split('|');
303
+ return { agentId, appId };
304
+ }
305
+
306
+ function createWidget() {
307
+ if (ecomWidget) {
308
+ ecomWidget.destroy();
309
+ ecomWidget = null;
310
+ }
311
+
312
+ const TTPAgentSDK = window.TTPAgentSDK;
313
+ if (!TTPAgentSDK || !TTPAgentSDK.TTPEcommerceWidget) {
314
+ updateStatus('TTPEcommerceWidget not available in SDK', 'error');
315
+ return;
316
+ }
317
+
318
+ const agent = getAgentConfig();
319
+
320
+ ecomWidget = new TTPAgentSDK.TTPEcommerceWidget({
321
+ agentId: agent.agentId,
322
+ appId: agent.appId,
323
+ language: document.getElementById('languageSelect').value,
324
+ direction: document.getElementById('dirSelect').value,
325
+ behavior: {
326
+ mode: document.getElementById('modeSelect').value,
327
+ startOpen: document.getElementById('startOpenSelect').value === 'true'
328
+ },
329
+ icon: {
330
+ type: 'custom',
331
+ customImage: 'https://talktopc.com/logo192.png',
332
+ size: 'medium',
333
+ backgroundColor: '#FFFFFF'
334
+ },
335
+ partner: { name: 'TestStore' },
336
+ cart: {
337
+ addToCartFn: async (productId, qty) => {
338
+ console.log('[TestPage] addToCartFn called:', productId, qty);
339
+ return { ok: true };
340
+ },
341
+ getCartFn: async () => {
342
+ console.log('[TestPage] getCartFn called');
343
+ return window.__TTP_ECOMMERCE__?.getCart() || { items: [], total: 0, count: 0 };
344
+ }
345
+ }
346
+ });
347
+
348
+ window.testWidget = ecomWidget;
349
+ updateStatus('TTPEcommerceWidget created successfully', 'success');
350
+ refreshCartDisplay();
351
+ }
352
+
353
+ // Button handlers
354
+ document.getElementById('createBtn').onclick = createWidget;
355
+
356
+ document.getElementById('destroyBtn').onclick = () => {
357
+ if (ecomWidget) {
358
+ ecomWidget.destroy();
359
+ ecomWidget = null;
360
+ updateStatus('Widget destroyed', '');
361
+ refreshCartDisplay();
362
+ }
363
+ };
364
+
365
+ document.getElementById('showProductsBtn').onclick = async () => {
366
+ if (!window.__TTP_ECOMMERCE__) {
367
+ updateStatus('Create widget first', 'error');
368
+ return;
369
+ }
370
+ const query = document.getElementById('productQuery').value || 'milk';
371
+ try {
372
+ await window.__TTP_ECOMMERCE__.showProducts(query);
373
+ updateStatus('showProducts("' + query + '") sent', 'success');
374
+ } catch (e) {
375
+ updateStatus('showProducts failed: ' + e.message, 'error');
376
+ }
377
+ };
378
+
379
+ document.getElementById('cartAddBtn').onclick = async () => {
380
+ if (!window.__TTP_ECOMMERCE__) {
381
+ updateStatus('Create widget first', 'error');
382
+ return;
383
+ }
384
+ try {
385
+ const baseUrl = window.__TTP_MOCK_API__ || 'https://backend.talktopc.com';
386
+ const response = await fetch(`${baseUrl}/api/partner/mock-store/products/search?q=milk&limit=1&sessionId=test`);
387
+ const data = await response.json();
388
+ const product = data.products[0];
389
+ window.__TTP_ECOMMERCE__.handleMessage({
390
+ t: 'cart_updated',
391
+ product: product,
392
+ action: 'added',
393
+ cartTotal: product.price,
394
+ cartItemCount: 1
395
+ });
396
+ updateStatus('Simulated cart_updated for "' + product.name + '"', 'success');
397
+ setTimeout(refreshCartDisplay, 200);
398
+ } catch (e) {
399
+ updateStatus('Failed to fetch product: ' + e.message, 'error');
400
+ }
401
+ };
402
+
403
+ document.getElementById('cartClearBtn').onclick = () => {
404
+ if (!window.__TTP_ECOMMERCE__) {
405
+ updateStatus('Create widget first', 'error');
406
+ return;
407
+ }
408
+ window.__TTP_ECOMMERCE__.clearCart();
409
+ updateStatus('Cart cleared', '');
410
+ refreshCartDisplay();
411
+ };
412
+
413
+ document.getElementById('refreshCartBtn').onclick = refreshCartDisplay;
414
+
415
+ // Wait for SDK and auto-create widget
416
+ function waitForSDK() {
417
+ return new Promise((resolve, reject) => {
418
+ if (window.TTPAgentSDK?.TTPEcommerceWidget) { resolve(); return; }
419
+ let attempts = 0;
420
+ const iv = setInterval(() => {
421
+ attempts++;
422
+ if (window.TTPAgentSDK?.TTPEcommerceWidget) { clearInterval(iv); resolve(); }
423
+ else if (attempts >= 50) { clearInterval(iv); reject(new Error('SDK failed to load')); }
424
+ }, 100);
425
+ });
426
+ }
427
+
428
+ waitForSDK().then(() => {
429
+ updateStatus('SDK loaded — creating widget...', '');
430
+ createWidget();
431
+ }).catch(e => {
432
+ updateStatus('SDK load failed: ' + e.message, 'error');
433
+ });
434
+ </script>
435
+ </body>
436
+ </html>
@@ -301,6 +301,21 @@
301
301
  <span class="badge" style="background: #fef3c7; color: #92400e;">Debug</span>
302
302
  </div>
303
303
  </a>
304
+
305
+ <a href="../examples/test-ecommerce.html" class="test-card">
306
+ <span class="test-card__icon">🛒</span>
307
+ <h3 class="test-card__title">E-Commerce Widget Test</h3>
308
+ <p class="test-card__description">
309
+ Test the TTPEcommerceWidget — a composition wrapper around TTPChatWidget
310
+ that adds product display, cart management, and partner integration.
311
+ Simulate show_products and cart_updated messages without a live voice call.
312
+ </p>
313
+ <div class="test-card__badges">
314
+ <span class="badge badge--widget">Widget</span>
315
+ <span class="badge badge--voice">Voice</span>
316
+ <span class="badge badge--new">E-Commerce</span>
317
+ </div>
318
+ </a>
304
319
  </div>
305
320
  </div>
306
321
 
@@ -327,8 +327,8 @@
327
327
  </label>
328
328
  <label id="labelLanguage">Language
329
329
  <select id="languageSelect">
330
- <option value="en">English</option>
331
- <option value="he" selected>עברית</option>
330
+ <option value="en" selected>English</option>
331
+ <option value="he">עברית</option>
332
332
  <option value="ar">العربية</option>
333
333
  <option value="ru">Русский</option>
334
334
  <option value="es">Español</option>
@@ -345,8 +345,8 @@
345
345
  </label>
346
346
  <label id="labelDirection">Direction
347
347
  <select id="dirSelect">
348
- <option value="ltr">LTR</option>
349
- <option value="rtl" selected>RTL</option>
348
+ <option value="ltr" selected>LTR</option>
349
+ <option value="rtl">RTL</option>
350
350
  </select>
351
351
  </label>
352
352
  <label id="labelPosition">Position
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ttp-agent-sdk",
3
- "version": "2.34.9",
3
+ "version": "2.34.12",
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",