ttp-agent-sdk 2.5.2 → 2.5.3

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.
@@ -178,7 +178,7 @@
178
178
  <div class="section">
179
179
  <h2 class="section__title">Voice SDK Tests</h2>
180
180
  <div class="test-grid">
181
- <a href="demo-v2.html" class="test-card">
181
+ <a href="../examples/demo-v2.html" class="test-card">
182
182
  <span class="test-card__icon">🎤</span>
183
183
  <h3 class="test-card__title">Voice SDK Demo (v2)</h3>
184
184
  <p class="test-card__description">
@@ -192,7 +192,7 @@
192
192
  </div>
193
193
  </a>
194
194
 
195
- <a href="test-signed-link.html" class="test-card">
195
+ <a href="../examples/test-signed-link.html" class="test-card">
196
196
  <span class="test-card__icon">🔐</span>
197
197
  <h3 class="test-card__title">Signed Link Test</h3>
198
198
  <p class="test-card__description">
@@ -205,7 +205,7 @@
205
205
  </div>
206
206
  </a>
207
207
 
208
- <a href="test.html" class="test-card">
208
+ <a href="../examples/test.html" class="test-card">
209
209
  <span class="test-card__icon">⚡</span>
210
210
  <h3 class="test-card__title">Basic Voice Test</h3>
211
211
  <p class="test-card__description">
@@ -223,7 +223,7 @@
223
223
  <div class="section">
224
224
  <h2 class="section__title">Text Chat Tests</h2>
225
225
  <div class="test-grid">
226
- <a href="test-text-chat.html" class="test-card">
226
+ <a href="../examples/test-text-chat.html" class="test-card">
227
227
  <span class="test-card__icon">đŸ’Ŧ</span>
228
228
  <h3 class="test-card__title">Text Chat SDK Test</h3>
229
229
  <p class="test-card__description">
@@ -0,0 +1,486 @@
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">
6
+ <title>TTP Chat Widget - Test Page</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
16
+ background: #f9fafb;
17
+ padding: 20px;
18
+ min-height: 100vh;
19
+ }
20
+
21
+ .container {
22
+ max-width: 1200px;
23
+ margin: 0 auto;
24
+ }
25
+
26
+ .header {
27
+ background: white;
28
+ padding: 32px;
29
+ border-radius: 16px;
30
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
31
+ margin-bottom: 24px;
32
+ }
33
+
34
+ .header h1 {
35
+ font-size: 32px;
36
+ font-weight: 700;
37
+ color: #111827;
38
+ margin-bottom: 8px;
39
+ }
40
+
41
+ .header p {
42
+ font-size: 16px;
43
+ color: #6b7280;
44
+ }
45
+
46
+ .back-link {
47
+ display: inline-block;
48
+ margin-bottom: 20px;
49
+ color: #4f46e5;
50
+ text-decoration: none;
51
+ font-weight: 500;
52
+ transition: color 0.2s;
53
+ }
54
+
55
+ .back-link:hover {
56
+ color: #4338ca;
57
+ }
58
+
59
+ .config-section {
60
+ background: white;
61
+ padding: 32px;
62
+ border-radius: 16px;
63
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
64
+ margin-bottom: 24px;
65
+ }
66
+
67
+ .config-section h2 {
68
+ font-size: 24px;
69
+ font-weight: 700;
70
+ color: #111827;
71
+ margin-bottom: 20px;
72
+ }
73
+
74
+ .config-grid {
75
+ display: grid;
76
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
77
+ gap: 20px;
78
+ margin-bottom: 24px;
79
+ }
80
+
81
+ .config-group {
82
+ display: flex;
83
+ flex-direction: column;
84
+ }
85
+
86
+ .config-group label {
87
+ font-size: 14px;
88
+ font-weight: 600;
89
+ color: #374151;
90
+ margin-bottom: 8px;
91
+ }
92
+
93
+ .config-group input,
94
+ .config-group select {
95
+ padding: 10px 12px;
96
+ border: 1px solid #d1d5db;
97
+ border-radius: 8px;
98
+ font-size: 14px;
99
+ transition: border-color 0.2s;
100
+ }
101
+
102
+ .config-group input:focus,
103
+ .config-group select:focus {
104
+ outline: none;
105
+ border-color: #4f46e5;
106
+ }
107
+
108
+ .info-box {
109
+ background: #eff6ff;
110
+ border-left: 4px solid #3b82f6;
111
+ padding: 16px;
112
+ border-radius: 8px;
113
+ margin-bottom: 24px;
114
+ }
115
+
116
+ .info-box h3 {
117
+ font-size: 16px;
118
+ font-weight: 600;
119
+ color: #1e40af;
120
+ margin-bottom: 8px;
121
+ }
122
+
123
+ .info-box p {
124
+ font-size: 14px;
125
+ color: #1e3a8a;
126
+ line-height: 1.6;
127
+ }
128
+
129
+ .info-box ul {
130
+ margin-top: 8px;
131
+ padding-left: 20px;
132
+ color: #1e3a8a;
133
+ }
134
+
135
+ .info-box li {
136
+ margin-bottom: 4px;
137
+ }
138
+
139
+ .warning-box {
140
+ background: #fef3c7;
141
+ border-left: 4px solid #f59e0b;
142
+ padding: 16px;
143
+ border-radius: 8px;
144
+ margin-bottom: 24px;
145
+ }
146
+
147
+ .warning-box h3 {
148
+ font-size: 16px;
149
+ font-weight: 600;
150
+ color: #92400e;
151
+ margin-bottom: 8px;
152
+ }
153
+
154
+ .warning-box p {
155
+ font-size: 14px;
156
+ color: #78350f;
157
+ line-height: 1.6;
158
+ }
159
+
160
+ .button-group {
161
+ display: flex;
162
+ gap: 12px;
163
+ flex-wrap: wrap;
164
+ }
165
+
166
+ .btn {
167
+ padding: 12px 24px;
168
+ border: none;
169
+ border-radius: 8px;
170
+ font-size: 16px;
171
+ font-weight: 600;
172
+ cursor: pointer;
173
+ transition: all 0.2s;
174
+ }
175
+
176
+ .btn-primary {
177
+ background: #4f46e5;
178
+ color: white;
179
+ }
180
+
181
+ .btn-primary:hover {
182
+ background: #4338ca;
183
+ transform: translateY(-1px);
184
+ }
185
+
186
+ .btn-secondary {
187
+ background: #e5e7eb;
188
+ color: #111827;
189
+ }
190
+
191
+ .btn-secondary:hover {
192
+ background: #d1d5db;
193
+ }
194
+
195
+ .status {
196
+ background: #f3f4f6;
197
+ padding: 16px;
198
+ border-radius: 8px;
199
+ margin-top: 24px;
200
+ font-family: monospace;
201
+ font-size: 14px;
202
+ color: #374151;
203
+ }
204
+
205
+ .status-item {
206
+ margin-bottom: 8px;
207
+ }
208
+
209
+ .status-item:last-child {
210
+ margin-bottom: 0;
211
+ }
212
+
213
+ .status-label {
214
+ font-weight: 600;
215
+ color: #111827;
216
+ }
217
+
218
+ @media (max-width: 768px) {
219
+ .header h1 {
220
+ font-size: 24px;
221
+ }
222
+
223
+ .config-grid {
224
+ grid-template-columns: 1fr;
225
+ }
226
+
227
+ .button-group {
228
+ flex-direction: column;
229
+ }
230
+
231
+ .btn {
232
+ width: 100%;
233
+ }
234
+ }
235
+ </style>
236
+ </head>
237
+ <body>
238
+ <div class="container">
239
+ <a href="test-index.html" class="back-link">← Back to Test Pages</a>
240
+
241
+ <div class="header">
242
+ <h1>🎨 TTP Chat Widget Test</h1>
243
+ <p>Test the unified voice and text chat widget with microphone permission handling</p>
244
+ </div>
245
+
246
+ <div class="warning-box">
247
+ <h3>📱 Mobile Browser Note</h3>
248
+ <p>
249
+ Microphone access requires HTTPS and must be triggered by a direct button tap.
250
+ If you see permission errors, ensure you're using HTTPS and tap the recording button directly.
251
+ </p>
252
+ </div>
253
+
254
+ <div class="info-box">
255
+ <h3>â„šī¸ About This Test</h3>
256
+ <p>
257
+ This page tests the <strong>TTPChatWidget</strong> which provides a unified interface for both
258
+ voice and text chat. The widget includes:
259
+ </p>
260
+ <ul>
261
+ <li>🎤 Voice call functionality with microphone permission handling</li>
262
+ <li>đŸ’Ŧ Text chat interface</li>
263
+ <li>🎨 Customizable styling and positioning</li>
264
+ <li>🌐 Multi-language support</li>
265
+ <li>📱 Mobile-responsive design</li>
266
+ </ul>
267
+ </div>
268
+
269
+ <div class="config-section">
270
+ <h2>âš™ī¸ Widget Configuration</h2>
271
+
272
+ <div class="config-grid">
273
+ <div class="config-group">
274
+ <label for="agentId">Agent ID *</label>
275
+ <input type="text" id="agentId" value="agent_e5cf06457" placeholder="agent_123">
276
+ </div>
277
+
278
+ <div class="config-group">
279
+ <label for="appId">App ID *</label>
280
+ <input type="text" id="appId" value="app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC" placeholder="app_456">
281
+ </div>
282
+
283
+ <div class="config-group">
284
+ <label for="getSessionUrl">Get Session URL</label>
285
+ <input type="text" id="getSessionUrl" value="" placeholder="https://your-api.com/get-session">
286
+ </div>
287
+
288
+ <div class="config-group">
289
+ <label for="websocketUrl">WebSocket URL</label>
290
+ <input type="text" id="websocketUrl" value="wss://speech.talktopc.com/ws/conv" placeholder="wss://...">
291
+ </div>
292
+
293
+ <div class="config-group">
294
+ <label for="position">Position</label>
295
+ <select id="position">
296
+ <option value="bottom-right" selected>Bottom Right</option>
297
+ <option value="bottom-left">Bottom Left</option>
298
+ <option value="top-right">Top Right</option>
299
+ <option value="top-left">Top Left</option>
300
+ </select>
301
+ </div>
302
+
303
+ <div class="config-group">
304
+ <label for="language">Language</label>
305
+ <select id="language">
306
+ <option value="en" selected>English</option>
307
+ <option value="he">Hebrew</option>
308
+ <option value="ar">Arabic</option>
309
+ <option value="ru">Russian</option>
310
+ <option value="es">Spanish</option>
311
+ <option value="fr">French</option>
312
+ <option value="de">German</option>
313
+ </select>
314
+ </div>
315
+
316
+ <div class="config-group">
317
+ <label for="mode">Widget Mode</label>
318
+ <select id="mode">
319
+ <option value="unified" selected>Unified (Voice + Text)</option>
320
+ <option value="voice-only">Voice Only</option>
321
+ <option value="text-only">Text Only</option>
322
+ </select>
323
+ </div>
324
+
325
+ <div class="config-group">
326
+ <label for="primaryColor">Primary Color</label>
327
+ <input type="color" id="primaryColor" value="#7C3AED">
328
+ </div>
329
+ </div>
330
+
331
+ <div class="button-group">
332
+ <button class="btn btn-primary" onclick="initializeWidget()">Initialize Widget</button>
333
+ <button class="btn btn-secondary" onclick="destroyWidget()">Destroy Widget</button>
334
+ <button class="btn btn-secondary" onclick="resetConfig()">Reset Config</button>
335
+ </div>
336
+
337
+ <div id="status" class="status" style="display: none;">
338
+ <div class="status-item">
339
+ <span class="status-label">Status:</span> <span id="statusText">Ready</span>
340
+ </div>
341
+ <div class="status-item">
342
+ <span class="status-label">Widget Initialized:</span> <span id="widgetStatus">No</span>
343
+ </div>
344
+ </div>
345
+ </div>
346
+
347
+ <div class="info-box">
348
+ <h3>📝 Test Scenarios</h3>
349
+ <p>Try these scenarios to test the widget:</p>
350
+ <ul>
351
+ <li><strong>Voice Call:</strong> Click "Voice Call" → Should show pre-prompt modal → Grant permission → Start call</li>
352
+ <li><strong>Permission Denied:</strong> Deny microphone permission → Should show blocked modal with instructions</li>
353
+ <li><strong>Text Chat:</strong> Click "Text Chat" → Send messages → Test conversation flow</li>
354
+ <li><strong>Widget Positioning:</strong> Change position and reinitialize to test different placements</li>
355
+ <li><strong>Language:</strong> Change language to test translations</li>
356
+ </ul>
357
+ </div>
358
+ </div>
359
+
360
+ <!-- Load SDK -->
361
+ <script type="module">
362
+ import { TTPChatWidget } from '../agent-widget.js';
363
+
364
+ window.TTPChatWidget = TTPChatWidget;
365
+ window.widgetInstance = null;
366
+
367
+ console.log('✅ SDK loaded successfully. TTPChatWidget:', TTPChatWidget);
368
+
369
+ window.initializeWidget = function() {
370
+ if (!window.TTPChatWidget) {
371
+ alert('TTPChatWidget is not available. Check browser console for errors.');
372
+ console.error('TTPChatWidget is undefined');
373
+ return;
374
+ }
375
+ const agentId = document.getElementById('agentId').value;
376
+ const appId = document.getElementById('appId').value;
377
+ const getSessionUrl = document.getElementById('getSessionUrl').value;
378
+ const websocketUrl = document.getElementById('websocketUrl').value;
379
+ const position = document.getElementById('position').value;
380
+ const language = document.getElementById('language').value;
381
+ const mode = document.getElementById('mode').value;
382
+ const primaryColor = document.getElementById('primaryColor').value;
383
+
384
+ if (!agentId || !appId) {
385
+ alert('Please provide Agent ID and App ID');
386
+ return;
387
+ }
388
+
389
+ // Destroy existing widget if any
390
+ if (window.widgetInstance) {
391
+ window.destroyWidget();
392
+ }
393
+
394
+ try {
395
+ const config = {
396
+ agentId: agentId,
397
+ appId: appId,
398
+ language: language,
399
+ primaryColor: primaryColor,
400
+ behavior: {
401
+ mode: mode
402
+ }
403
+ };
404
+
405
+ // Add optional configs
406
+ if (getSessionUrl) {
407
+ config.getSessionUrl = getSessionUrl;
408
+ }
409
+
410
+ if (websocketUrl) {
411
+ config.websocketUrl = websocketUrl;
412
+ }
413
+
414
+ // Handle position
415
+ if (position) {
416
+ const [vertical, horizontal] = position.split('-');
417
+ config.position = {
418
+ vertical: vertical,
419
+ horizontal: horizontal,
420
+ offset: { x: 20, y: 20 }
421
+ };
422
+ }
423
+
424
+ console.log('Initializing widget with config:', config);
425
+ console.log('TTPChatWidget constructor:', window.TTPChatWidget);
426
+ window.widgetInstance = new window.TTPChatWidget(config);
427
+ console.log('Widget instance created:', window.widgetInstance);
428
+
429
+ // Update status
430
+ document.getElementById('status').style.display = 'block';
431
+ document.getElementById('statusText').textContent = 'Widget initialized';
432
+ document.getElementById('widgetStatus').textContent = 'Yes';
433
+
434
+ console.log('✅ Widget initialized successfully');
435
+ } catch (error) {
436
+ console.error('❌ Error initializing widget:', error);
437
+ alert('Error initializing widget: ' + error.message);
438
+ document.getElementById('statusText').textContent = 'Error: ' + error.message;
439
+ }
440
+ };
441
+
442
+ window.destroyWidget = function() {
443
+ if (window.widgetInstance) {
444
+ try {
445
+ // Widget doesn't have a destroy method, but we can remove it from DOM
446
+ const widgetButton = document.getElementById('text-chat-button');
447
+ const widgetPanel = document.getElementById('text-chat-panel');
448
+
449
+ if (widgetButton && widgetButton.parentNode) {
450
+ widgetButton.parentNode.removeChild(widgetButton);
451
+ }
452
+ if (widgetPanel && widgetPanel.parentNode) {
453
+ widgetPanel.parentNode.removeChild(widgetPanel);
454
+ }
455
+
456
+ window.widgetInstance = null;
457
+ document.getElementById('statusText').textContent = 'Widget destroyed';
458
+ document.getElementById('widgetStatus').textContent = 'No';
459
+ console.log('✅ Widget destroyed');
460
+ } catch (error) {
461
+ console.error('❌ Error destroying widget:', error);
462
+ }
463
+ }
464
+ };
465
+
466
+ window.resetConfig = function() {
467
+ document.getElementById('agentId').value = 'agent_e5cf06457';
468
+ document.getElementById('appId').value = 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC';
469
+ document.getElementById('getSessionUrl').value = '';
470
+ document.getElementById('websocketUrl').value = 'wss://speech.talktopc.com/ws/conv';
471
+ document.getElementById('position').value = 'bottom-right';
472
+ document.getElementById('language').value = 'en';
473
+ document.getElementById('mode').value = 'unified';
474
+ document.getElementById('primaryColor').value = '#7C3AED';
475
+ };
476
+
477
+ // Auto-initialize on load (optional)
478
+ // window.addEventListener('DOMContentLoaded', () => {
479
+ // setTimeout(() => {
480
+ // window.initializeWidget();
481
+ // }, 1000);
482
+ // });
483
+ </script>
484
+ </body>
485
+ </html>
486
+
@@ -178,7 +178,7 @@
178
178
  <div class="section">
179
179
  <h2 class="section__title">Voice SDK Tests</h2>
180
180
  <div class="test-grid">
181
- <a href="demo-v2.html" class="test-card">
181
+ <a href="../examples/demo-v2.html" class="test-card">
182
182
  <span class="test-card__icon">🎤</span>
183
183
  <h3 class="test-card__title">Voice SDK Demo (v2)</h3>
184
184
  <p class="test-card__description">
@@ -192,7 +192,7 @@
192
192
  </div>
193
193
  </a>
194
194
 
195
- <a href="test-signed-link.html" class="test-card">
195
+ <a href="../examples/test-signed-link.html" class="test-card">
196
196
  <span class="test-card__icon">🔐</span>
197
197
  <h3 class="test-card__title">Signed Link Test</h3>
198
198
  <p class="test-card__description">
@@ -205,7 +205,7 @@
205
205
  </div>
206
206
  </a>
207
207
 
208
- <a href="test.html" class="test-card">
208
+ <a href="../examples/test.html" class="test-card">
209
209
  <span class="test-card__icon">⚡</span>
210
210
  <h3 class="test-card__title">Basic Voice Test</h3>
211
211
  <p class="test-card__description">
@@ -223,7 +223,7 @@
223
223
  <div class="section">
224
224
  <h2 class="section__title">Text Chat Tests</h2>
225
225
  <div class="test-grid">
226
- <a href="test-text-chat.html" class="test-card">
226
+ <a href="../examples/test-text-chat.html" class="test-card">
227
227
  <span class="test-card__icon">đŸ’Ŧ</span>
228
228
  <h3 class="test-card__title">Text Chat SDK Test</h3>
229
229
  <p class="test-card__description">
@@ -359,12 +359,19 @@
359
359
 
360
360
  <!-- Load SDK -->
361
361
  <script type="module">
362
- import { TTPChatWidget } from '../dist/agent-widget.js';
362
+ import { TTPChatWidget } from '../agent-widget.js';
363
363
 
364
364
  window.TTPChatWidget = TTPChatWidget;
365
365
  window.widgetInstance = null;
366
366
 
367
+ console.log('✅ SDK loaded successfully. TTPChatWidget:', TTPChatWidget);
368
+
367
369
  window.initializeWidget = function() {
370
+ if (!window.TTPChatWidget) {
371
+ alert('TTPChatWidget is not available. Check browser console for errors.');
372
+ console.error('TTPChatWidget is undefined');
373
+ return;
374
+ }
368
375
  const agentId = document.getElementById('agentId').value;
369
376
  const appId = document.getElementById('appId').value;
370
377
  const getSessionUrl = document.getElementById('getSessionUrl').value;
@@ -415,7 +422,9 @@
415
422
  }
416
423
 
417
424
  console.log('Initializing widget with config:', config);
418
- window.widgetInstance = new TTPChatWidget(config);
425
+ console.log('TTPChatWidget constructor:', window.TTPChatWidget);
426
+ window.widgetInstance = new window.TTPChatWidget(config);
427
+ console.log('Widget instance created:', window.widgetInstance);
419
428
 
420
429
  // Update status
421
430
  document.getElementById('status').style.display = 'block';
@@ -19,8 +19,8 @@
19
19
  <!-- Address bar area -->
20
20
  <rect x="10" y="50" width="480" height="40" fill="white" rx="20" filter="url(#shadow)"/>
21
21
 
22
- <!-- HIGHLIGHTED Icon area (lock or info) -->
23
- <rect x="12" y="52" width="85" height="36" fill="#e8f5e9" rx="18 0 0 18"/>
22
+ <!-- HIGHLIGHTED Icon area (lock, info, or settings) -->
23
+ <rect x="12" y="52" width="115" height="36" fill="#e8f5e9" rx="18 0 0 18"/>
24
24
  <rect x="12" y="52" width="4" height="36" fill="#4caf50" rx="2"/>
25
25
 
26
26
  <!-- Lock icon -->
@@ -31,15 +31,19 @@
31
31
  <circle cx="65" cy="70" r="12" fill="#1a73e8" opacity="0.7"/>
32
32
  <text x="60" y="76" font-family="Arial, sans-serif" font-size="12" fill="white" font-weight="bold">i</text>
33
33
 
34
+ <!-- Settings icon (alternative) - three vertical dots ⋮ -->
35
+ <circle cx="95" cy="70" r="12" fill="#5f6368" opacity="0.7"/>
36
+ <text x="95" y="75" font-family="Arial, sans-serif" font-size="16" fill="white" text-anchor="middle" font-weight="bold">⋮</text>
37
+
34
38
  <!-- URL text -->
35
- <text x="100" y="76" font-family="Segoe UI, Arial, sans-serif" font-size="14" fill="#202124">your-website.com/voice-call</text>
39
+ <text x="130" y="76" font-family="Segoe UI, Arial, sans-serif" font-size="14" fill="#202124">your-website.com/voice-call</text>
36
40
 
37
41
  <!-- Pointer arrow -->
38
- <path d="M 50 95 L 50 105 L 40 100 Z" fill="#4caf50"/>
39
- <path d="M 50 95 L 50 105 L 60 100 Z" fill="#4caf50"/>
40
- <rect x="35" y="105" width="30" height="2" fill="#4caf50"/>
42
+ <path d="M 65 95 L 65 105 L 55 100 Z" fill="#4caf50"/>
43
+ <path d="M 65 95 L 65 105 L 75 100 Z" fill="#4caf50"/>
44
+ <rect x="50" y="105" width="30" height="2" fill="#4caf50"/>
41
45
 
42
46
  <!-- Instruction text -->
43
- <rect x="95" y="95" width="180" height="22" rx="4" fill="#4caf50"/>
44
- <text x="107" y="111" font-family="Segoe UI, Arial, sans-serif" font-size="12" fill="white" font-weight="600">👆 Click lock 🔒 or info â„šī¸ icon</text>
47
+ <rect x="125" y="95" width="200" height="22" rx="4" fill="#4caf50"/>
48
+ <text x="137" y="111" font-family="Segoe UI, Arial, sans-serif" font-size="11" fill="white" font-weight="600">👆 Click 🔒 â„šī¸ or ⋮ icon</text>
45
49
  </svg>
@@ -178,7 +178,7 @@
178
178
  <div class="section">
179
179
  <h2 class="section__title">Voice SDK Tests</h2>
180
180
  <div class="test-grid">
181
- <a href="demo-v2.html" class="test-card">
181
+ <a href="../examples/demo-v2.html" class="test-card">
182
182
  <span class="test-card__icon">🎤</span>
183
183
  <h3 class="test-card__title">Voice SDK Demo (v2)</h3>
184
184
  <p class="test-card__description">
@@ -192,7 +192,7 @@
192
192
  </div>
193
193
  </a>
194
194
 
195
- <a href="test-signed-link.html" class="test-card">
195
+ <a href="../examples/test-signed-link.html" class="test-card">
196
196
  <span class="test-card__icon">🔐</span>
197
197
  <h3 class="test-card__title">Signed Link Test</h3>
198
198
  <p class="test-card__description">
@@ -205,7 +205,7 @@
205
205
  </div>
206
206
  </a>
207
207
 
208
- <a href="test.html" class="test-card">
208
+ <a href="../examples/test.html" class="test-card">
209
209
  <span class="test-card__icon">⚡</span>
210
210
  <h3 class="test-card__title">Basic Voice Test</h3>
211
211
  <p class="test-card__description">
@@ -223,7 +223,7 @@
223
223
  <div class="section">
224
224
  <h2 class="section__title">Text Chat Tests</h2>
225
225
  <div class="test-grid">
226
- <a href="test-text-chat.html" class="test-card">
226
+ <a href="../examples/test-text-chat.html" class="test-card">
227
227
  <span class="test-card__icon">đŸ’Ŧ</span>
228
228
  <h3 class="test-card__title">Text Chat SDK Test</h3>
229
229
  <p class="test-card__description">