ttp-agent-sdk 2.2.9 → 2.2.10
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 +1 -1
- package/dist/agent-widget.js +1 -1
- package/dist/agent-widget.js.map +1 -1
- package/dist/examples/test-text-chat.html +7 -7
- package/dist/examples/test.html +3 -3
- package/dist/examples/translations.json +1 -0
- package/dist/index.html +1 -1
- package/examples/test-text-chat.html +7 -7
- package/examples/test.html +3 -3
- package/examples/translations.json +1 -0
- package/package.json +1 -1
- package/dist/examples/test-agent-app.html +0 -1209
- package/examples/test-agent-app.html +0 -1209
|
@@ -1,1209 +0,0 @@
|
|
|
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>Voice Agent Widget - Agent ID + App ID Test</title>
|
|
7
|
-
<style>
|
|
8
|
-
body {
|
|
9
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
10
|
-
max-width: 800px;
|
|
11
|
-
margin: 40px auto;
|
|
12
|
-
padding: 20px;
|
|
13
|
-
background: #F9FAFB;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
@media (max-width: 768px) {
|
|
17
|
-
body {
|
|
18
|
-
margin: 0;
|
|
19
|
-
padding: 10px;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
.container {
|
|
24
|
-
background: white;
|
|
25
|
-
padding: 30px;
|
|
26
|
-
border-radius: 12px;
|
|
27
|
-
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
@media (max-width: 768px) {
|
|
31
|
-
.container {
|
|
32
|
-
padding: 16px;
|
|
33
|
-
border-radius: 8px;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
h1 {
|
|
38
|
-
color: #111827;
|
|
39
|
-
margin-top: 0;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.info {
|
|
43
|
-
background: #EFF6FF;
|
|
44
|
-
border-left: 4px solid #3B82F6;
|
|
45
|
-
padding: 16px;
|
|
46
|
-
margin: 20px 0;
|
|
47
|
-
border-radius: 4px;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.config-info {
|
|
51
|
-
background: #F0FDF4;
|
|
52
|
-
border-left: 4px solid #10B981;
|
|
53
|
-
padding: 16px;
|
|
54
|
-
margin: 20px 0;
|
|
55
|
-
border-radius: 4px;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.status {
|
|
59
|
-
margin: 20px 0;
|
|
60
|
-
padding: 12px;
|
|
61
|
-
background: #F3F4F6;
|
|
62
|
-
border-radius: 6px;
|
|
63
|
-
font-family: monospace;
|
|
64
|
-
font-size: 14px;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.status.success {
|
|
68
|
-
background: #D1FAE5;
|
|
69
|
-
color: #065F46;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.status.error {
|
|
73
|
-
background: #FEE2E2;
|
|
74
|
-
color: #991B1B;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
button {
|
|
78
|
-
background: #4F46E5;
|
|
79
|
-
color: white;
|
|
80
|
-
border: none;
|
|
81
|
-
padding: 12px 24px;
|
|
82
|
-
border-radius: 6px;
|
|
83
|
-
cursor: pointer;
|
|
84
|
-
font-size: 16px;
|
|
85
|
-
margin: 10px 10px 10px 0;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
button:hover {
|
|
89
|
-
background: #4338CA;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.code-block {
|
|
93
|
-
background: #1F2937;
|
|
94
|
-
color: #F9FAFB;
|
|
95
|
-
padding: 16px;
|
|
96
|
-
border-radius: 6px;
|
|
97
|
-
font-family: monospace;
|
|
98
|
-
font-size: 12px;
|
|
99
|
-
overflow-x: auto;
|
|
100
|
-
margin: 20px 0;
|
|
101
|
-
white-space: pre;
|
|
102
|
-
-webkit-overflow-scrolling: touch;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
@media (max-width: 768px) {
|
|
106
|
-
.code-block {
|
|
107
|
-
font-size: 11px;
|
|
108
|
-
padding: 12px;
|
|
109
|
-
margin: 16px 0;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.code-block pre {
|
|
114
|
-
margin: 0;
|
|
115
|
-
font-family: inherit;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
.code-block code {
|
|
119
|
-
font-family: inherit;
|
|
120
|
-
white-space: pre;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.tabs {
|
|
124
|
-
display: flex;
|
|
125
|
-
gap: 10px;
|
|
126
|
-
margin-bottom: 15px;
|
|
127
|
-
border-bottom: 2px solid #E5E7EB;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.tab {
|
|
131
|
-
background: none;
|
|
132
|
-
border: none;
|
|
133
|
-
padding: 12px 24px;
|
|
134
|
-
cursor: pointer;
|
|
135
|
-
font-size: 14px;
|
|
136
|
-
font-weight: 600;
|
|
137
|
-
color: #6B7280;
|
|
138
|
-
border-bottom: 3px solid transparent;
|
|
139
|
-
transition: all 0.2s;
|
|
140
|
-
margin-bottom: -2px;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
.tab:hover {
|
|
144
|
-
color: #4F46E5;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
.tab.active {
|
|
148
|
-
color: #4F46E5;
|
|
149
|
-
border-bottom-color: #4F46E5;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
.tab-content {
|
|
153
|
-
display: none;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.tab-content.active {
|
|
157
|
-
display: block;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.controls-panel {
|
|
161
|
-
background: white;
|
|
162
|
-
border: 2px solid #E5E7EB;
|
|
163
|
-
border-radius: 8px;
|
|
164
|
-
padding: 20px;
|
|
165
|
-
margin: 20px 0;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
.control-row {
|
|
169
|
-
display: grid;
|
|
170
|
-
grid-template-columns: 150px 150px 1fr auto;
|
|
171
|
-
gap: 12px;
|
|
172
|
-
align-items: center;
|
|
173
|
-
margin-bottom: 12px;
|
|
174
|
-
padding: 12px;
|
|
175
|
-
background: #F9FAFB;
|
|
176
|
-
border-radius: 6px;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
@media (max-width: 768px) {
|
|
180
|
-
.control-row {
|
|
181
|
-
grid-template-columns: 1fr;
|
|
182
|
-
gap: 8px;
|
|
183
|
-
padding: 12px;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
.control-row > * {
|
|
187
|
-
width: 100%;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
.control-row > div:last-child {
|
|
191
|
-
display: flex;
|
|
192
|
-
gap: 8px;
|
|
193
|
-
margin-top: 8px;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
.control-row button {
|
|
197
|
-
flex: 1;
|
|
198
|
-
padding: 10px;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
.control-row label {
|
|
203
|
-
font-weight: 600;
|
|
204
|
-
color: #374151;
|
|
205
|
-
font-size: 13px;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.control-row select,
|
|
209
|
-
.control-row input[type="text"],
|
|
210
|
-
.control-row input[type="color"] {
|
|
211
|
-
padding: 8px 12px;
|
|
212
|
-
border: 1px solid #D1D5DB;
|
|
213
|
-
border-radius: 4px;
|
|
214
|
-
font-size: 14px;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
.control-row input[type="color"] {
|
|
218
|
-
width: 60px;
|
|
219
|
-
height: 40px;
|
|
220
|
-
cursor: pointer;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
.control-row button {
|
|
224
|
-
padding: 8px 16px;
|
|
225
|
-
background: #3B82F6;
|
|
226
|
-
color: white;
|
|
227
|
-
border: none;
|
|
228
|
-
border-radius: 4px;
|
|
229
|
-
cursor: pointer;
|
|
230
|
-
font-size: 13px;
|
|
231
|
-
margin: 0;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
.control-row button:hover {
|
|
235
|
-
background: #2563EB;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
.control-row button.remove {
|
|
239
|
-
background: #EF4444;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
.control-row button.remove:hover {
|
|
243
|
-
background: #DC2626;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
@media (max-width: 768px) {
|
|
247
|
-
body {
|
|
248
|
-
font-size: 14px;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
h1 {
|
|
252
|
-
font-size: 24px;
|
|
253
|
-
margin-top: 0;
|
|
254
|
-
margin-bottom: 16px;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
h2 {
|
|
258
|
-
font-size: 20px;
|
|
259
|
-
margin-top: 24px;
|
|
260
|
-
margin-bottom: 12px;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
.info, .config-info {
|
|
264
|
-
padding: 12px;
|
|
265
|
-
margin: 16px 0;
|
|
266
|
-
font-size: 14px;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
.info ul, .config-info ul {
|
|
270
|
-
margin: 8px 0 0 16px;
|
|
271
|
-
padding-left: 16px;
|
|
272
|
-
line-height: 1.6;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
.info ol {
|
|
276
|
-
margin: 8px 0 0 16px;
|
|
277
|
-
padding-left: 16px;
|
|
278
|
-
line-height: 1.6;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
.status {
|
|
282
|
-
padding: 10px;
|
|
283
|
-
font-size: 12px;
|
|
284
|
-
margin: 16px 0;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
button {
|
|
288
|
-
padding: 12px 20px;
|
|
289
|
-
font-size: 14px;
|
|
290
|
-
margin: 8px 8px 8px 0;
|
|
291
|
-
touch-action: manipulation;
|
|
292
|
-
min-height: 44px;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
.tabs {
|
|
296
|
-
flex-wrap: wrap;
|
|
297
|
-
gap: 8px;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
.tab {
|
|
301
|
-
padding: 10px 16px;
|
|
302
|
-
font-size: 13px;
|
|
303
|
-
min-height: 44px;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
.controls-panel {
|
|
307
|
-
padding: 16px;
|
|
308
|
-
margin: 16px 0;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
.controls-panel button {
|
|
312
|
-
width: 100%;
|
|
313
|
-
margin: 8px 0;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
.control-row {
|
|
317
|
-
padding: 12px;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
.control-row select,
|
|
321
|
-
.control-row input[type="text"],
|
|
322
|
-
.control-row input[type="color"] {
|
|
323
|
-
font-size: 16px; /* Prevents iOS zoom on focus */
|
|
324
|
-
min-height: 44px;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
.control-row input[type="color"] {
|
|
328
|
-
min-width: 50px;
|
|
329
|
-
min-height: 50px;
|
|
330
|
-
width: 50px;
|
|
331
|
-
height: 50px;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
#log {
|
|
335
|
-
font-size: 11px;
|
|
336
|
-
max-height: 200px;
|
|
337
|
-
padding: 12px;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
@media (max-width: 480px) {
|
|
342
|
-
button {
|
|
343
|
-
width: 100%;
|
|
344
|
-
margin: 8px 0;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
.tabs {
|
|
348
|
-
flex-direction: column;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.tab {
|
|
352
|
-
width: 100%;
|
|
353
|
-
text-align: left;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
</style>
|
|
357
|
-
</head>
|
|
358
|
-
<body>
|
|
359
|
-
<div class="container">
|
|
360
|
-
<h1>🎤 Voice Agent Widget - Agent ID + App ID Test</h1>
|
|
361
|
-
|
|
362
|
-
<div class="config-info">
|
|
363
|
-
<strong>📝 Configuration:</strong>
|
|
364
|
-
<ul style="margin: 10px 0 0 20px; line-height: 1.8;">
|
|
365
|
-
<li><strong>Agent ID:</strong> agent_87c4a55a1</li>
|
|
366
|
-
<li><strong>App ID:</strong> app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC</li>
|
|
367
|
-
<li><strong>Method:</strong> Direct connection (no signed link)</li>
|
|
368
|
-
</ul>
|
|
369
|
-
</div>
|
|
370
|
-
|
|
371
|
-
<div class="info">
|
|
372
|
-
<strong>📝 Testing Instructions:</strong>
|
|
373
|
-
<ol style="margin: 10px 0 0 20px; line-height: 1.8;">
|
|
374
|
-
<li>Look for the floating voice button in the bottom-right corner</li>
|
|
375
|
-
<li>Click the button to open the widget</li>
|
|
376
|
-
<li>Click the voice button to start (will request microphone permission)</li>
|
|
377
|
-
<li>Widget will connect directly using agent ID + app ID</li>
|
|
378
|
-
<li>Check the status updates below</li>
|
|
379
|
-
<li>Try the interactive customization designer below to customize colors, sizes, text, and more in real-time!</li>
|
|
380
|
-
</ol>
|
|
381
|
-
</div>
|
|
382
|
-
|
|
383
|
-
<h2>Widget Status:</h2>
|
|
384
|
-
<div id="status" class="status">
|
|
385
|
-
Waiting for widget to load...
|
|
386
|
-
</div>
|
|
387
|
-
|
|
388
|
-
<h2>Console Log:</h2>
|
|
389
|
-
<div id="log" style="background: #1F2937; color: #F9FAFB; padding: 16px; border-radius: 6px; font-family: monospace; font-size: 12px; max-height: 300px; overflow-y: auto;">
|
|
390
|
-
Console messages will appear here...
|
|
391
|
-
</div>
|
|
392
|
-
|
|
393
|
-
<h2>Implementation Code:</h2>
|
|
394
|
-
<div class="tabs">
|
|
395
|
-
<button class="tab active" onclick="switchTab('simple')">Simple</button>
|
|
396
|
-
<button class="tab" onclick="switchTab('advanced')">All Options</button>
|
|
397
|
-
</div>
|
|
398
|
-
|
|
399
|
-
<div id="simple-tab" class="tab-content active">
|
|
400
|
-
<div class="code-block"><pre><code>const widget = new TTPAgentSDK.AgentWidget({
|
|
401
|
-
agentId: 'agent_87c4a55a1',
|
|
402
|
-
appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC',
|
|
403
|
-
|
|
404
|
-
primaryColor: '#10B981',
|
|
405
|
-
position: 'bottom-right',
|
|
406
|
-
|
|
407
|
-
// Icon configuration
|
|
408
|
-
icon: {
|
|
409
|
-
type: 'custom',
|
|
410
|
-
customImage: 'https://talktopc.com/logo192.png',
|
|
411
|
-
size: 'medium'
|
|
412
|
-
},
|
|
413
|
-
|
|
414
|
-
// Floating button (main button) colors - WHITE
|
|
415
|
-
button: {
|
|
416
|
-
backgroundColor: '#FFFFFF', // White floating button
|
|
417
|
-
hoverColor: '#E5E7EB' // Gray on hover
|
|
418
|
-
},
|
|
419
|
-
|
|
420
|
-
// Header (top of panel) colors - LIGHT PURPLE
|
|
421
|
-
header: {
|
|
422
|
-
title: 'TTP Support',
|
|
423
|
-
backgroundColor: '#A78BFA', // Light purple header
|
|
424
|
-
textColor: '#FFFFFF'
|
|
425
|
-
},
|
|
426
|
-
|
|
427
|
-
// Mic button (inside panel) colors - GRAY
|
|
428
|
-
panel: {
|
|
429
|
-
micButtonColor: '#E5E7EB', // Gray mic button
|
|
430
|
-
micButtonActiveColor: '#EF4444' // Red when active
|
|
431
|
-
}
|
|
432
|
-
});</code></pre></div>
|
|
433
|
-
</div>
|
|
434
|
-
|
|
435
|
-
<h2>🎨 Interactive Customization</h2>
|
|
436
|
-
<div class="controls-panel">
|
|
437
|
-
<div style="margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid #E5E7EB;">
|
|
438
|
-
<strong style="color: #374151;">Customize widget colors and properties in real-time:</strong>
|
|
439
|
-
</div>
|
|
440
|
-
|
|
441
|
-
<div id="control-rows">
|
|
442
|
-
<!-- Control rows will be added dynamically -->
|
|
443
|
-
</div>
|
|
444
|
-
|
|
445
|
-
<button id="add-control-btn" style="margin-top: 12px; padding: 10px 20px; background: #10B981;">
|
|
446
|
-
+ Add Customization
|
|
447
|
-
</button>
|
|
448
|
-
|
|
449
|
-
<div style="margin-top: 16px; padding-top: 16px; border-top: 1px solid #E5E7EB;">
|
|
450
|
-
<button id="reset-defaults-btn" style="background: #6B7280;">
|
|
451
|
-
Reset to Defaults
|
|
452
|
-
</button>
|
|
453
|
-
</div>
|
|
454
|
-
</div>
|
|
455
|
-
|
|
456
|
-
<h2>Implementation Code:</h2>
|
|
457
|
-
<div class="tabs">
|
|
458
|
-
<button class="tab active" onclick="switchTab('simple')">Simple</button>
|
|
459
|
-
<button class="tab" onclick="switchTab('advanced')">All Options</button>
|
|
460
|
-
</div>
|
|
461
|
-
|
|
462
|
-
<div id="advanced-tab" class="tab-content">
|
|
463
|
-
<div class="code-block"><pre><code>const widget = new TTPAgentSDK.AgentWidget({
|
|
464
|
-
// Required
|
|
465
|
-
agentId: 'agent_87c4a55a1',
|
|
466
|
-
appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC',
|
|
467
|
-
|
|
468
|
-
// Optional: getSessionUrl - only needed for signed links or custom URL logic
|
|
469
|
-
// getSessionUrl: async ({ agentId, appId, variables }) => {
|
|
470
|
-
// const response = await fetch('https://your-backend.com/api/signed-url', {
|
|
471
|
-
// method: 'POST',
|
|
472
|
-
// headers: { 'Content-Type': 'application/json' },
|
|
473
|
-
// body: JSON.stringify({ agentId, appId, variables })
|
|
474
|
-
// });
|
|
475
|
-
// const data = await response.json();
|
|
476
|
-
// return data.signedUrl;
|
|
477
|
-
// },
|
|
478
|
-
|
|
479
|
-
// Simple styling (backward compatible)
|
|
480
|
-
primaryColor: '#10B981',
|
|
481
|
-
position: 'bottom-right', // or use advanced position object below
|
|
482
|
-
|
|
483
|
-
// Icon Configuration
|
|
484
|
-
icon: {
|
|
485
|
-
type: 'custom', // 'microphone', 'custom', 'emoji', 'text'
|
|
486
|
-
customImage: 'https://talktopc.com/logo192.png', // For type: 'custom'
|
|
487
|
-
size: 'medium' // 'small', 'medium', 'large', 'xl'
|
|
488
|
-
},
|
|
489
|
-
|
|
490
|
-
// Button Configuration - Floating Button (Main Button) - WHITE
|
|
491
|
-
button: {
|
|
492
|
-
size: 'medium', // 'small', 'medium', 'large', 'xl'
|
|
493
|
-
shape: 'circle', // 'circle', 'square', 'rounded'
|
|
494
|
-
backgroundColor: '#FFFFFF', // Floating button background color (WHITE)
|
|
495
|
-
hoverColor: '#E5E7EB', // Floating button hover color (gray)
|
|
496
|
-
shadow: true,
|
|
497
|
-
shadowColor: 'rgba(0,0,0,0.15)'
|
|
498
|
-
},
|
|
499
|
-
|
|
500
|
-
// Header Configuration - Top of Panel - LIGHT PURPLE
|
|
501
|
-
header: {
|
|
502
|
-
title: 'TTP Support', // Custom title for the widget header
|
|
503
|
-
showTitle: true, // Show/hide title
|
|
504
|
-
backgroundColor: '#A78BFA', // Header background color (LIGHT PURPLE)
|
|
505
|
-
textColor: '#FFFFFF', // Header text color
|
|
506
|
-
showCloseButton: true
|
|
507
|
-
},
|
|
508
|
-
|
|
509
|
-
// Panel Configuration - Includes Mic Button Colors - GRAY
|
|
510
|
-
panel: {
|
|
511
|
-
width: 350,
|
|
512
|
-
height: 500,
|
|
513
|
-
borderRadius: 12,
|
|
514
|
-
backgroundColor: 'rgba(255,255,255,0.95)', // Panel background
|
|
515
|
-
backdropFilter: null,
|
|
516
|
-
border: '1px solid rgba(0,0,0,0.1)',
|
|
517
|
-
micButtonColor: '#E5E7EB', // Mic button (inside panel) background color (GRAY)
|
|
518
|
-
micButtonActiveColor: '#EF4444' // Mic button color when active/recording (RED)
|
|
519
|
-
},
|
|
520
|
-
// icon: {
|
|
521
|
-
// type: 'microphone',
|
|
522
|
-
// emoji: '🎤', // For type: 'emoji'
|
|
523
|
-
// text: 'AI', // For type: 'text'
|
|
524
|
-
// size: 'medium'
|
|
525
|
-
// },
|
|
526
|
-
|
|
527
|
-
// Advanced Positioning
|
|
528
|
-
// position: {
|
|
529
|
-
// vertical: 'bottom', // 'top', 'bottom', 'center'
|
|
530
|
-
// horizontal: 'right', // 'left', 'right', 'center'
|
|
531
|
-
// offset: { x: 20, y: 20 } // Custom offset in pixels
|
|
532
|
-
// },
|
|
533
|
-
|
|
534
|
-
// Button Configuration
|
|
535
|
-
// button: {
|
|
536
|
-
// size: 'medium', // 'small', 'medium', 'large', 'xl'
|
|
537
|
-
// shape: 'circle', // 'circle', 'square', 'rounded'
|
|
538
|
-
// primaryColor: '#10B981',
|
|
539
|
-
// hoverColor: '#059669',
|
|
540
|
-
// activeColor: '#EF4444',
|
|
541
|
-
// shadow: true,
|
|
542
|
-
// shadowColor: 'rgba(0,0,0,0.15)'
|
|
543
|
-
// },
|
|
544
|
-
|
|
545
|
-
// Panel Configuration
|
|
546
|
-
// panel: {
|
|
547
|
-
// width: 350,
|
|
548
|
-
// height: 500,
|
|
549
|
-
// borderRadius: 12,
|
|
550
|
-
// backgroundColor: 'rgba(255,255,255,0.95)',
|
|
551
|
-
// backdropFilter: 'blur(10px)', // Glass morphism effect
|
|
552
|
-
// border: '1px solid rgba(0,0,0,0.1)'
|
|
553
|
-
// },
|
|
554
|
-
|
|
555
|
-
// Header Configuration
|
|
556
|
-
// header: {
|
|
557
|
-
// title: 'Voice Assistant',
|
|
558
|
-
// showTitle: true,
|
|
559
|
-
// backgroundColor: null, // Uses button primaryColor if null
|
|
560
|
-
// textColor: '#FFFFFF',
|
|
561
|
-
// showCloseButton: true
|
|
562
|
-
// },
|
|
563
|
-
|
|
564
|
-
// Messages Configuration
|
|
565
|
-
// messages: {
|
|
566
|
-
// userBackgroundColor: '#E5E7EB',
|
|
567
|
-
// agentBackgroundColor: '#F3F4F6',
|
|
568
|
-
// systemBackgroundColor: '#DCFCE7',
|
|
569
|
-
// errorBackgroundColor: '#FEE2E2',
|
|
570
|
-
// textColor: '#1F2937',
|
|
571
|
-
// fontSize: '14px',
|
|
572
|
-
// borderRadius: 8
|
|
573
|
-
// },
|
|
574
|
-
|
|
575
|
-
// Animation Configuration
|
|
576
|
-
// animation: {
|
|
577
|
-
// enableHover: true,
|
|
578
|
-
// enablePulse: true,
|
|
579
|
-
// enableSlide: true,
|
|
580
|
-
// duration: 0.3
|
|
581
|
-
// },
|
|
582
|
-
|
|
583
|
-
// Behavior Configuration
|
|
584
|
-
// behavior: {
|
|
585
|
-
// startOpen: false, // Start with panel open on page load
|
|
586
|
-
// hidden: false, // Hide the floating button when true
|
|
587
|
-
// autoOpen: false, // Legacy: kept for backward-compatibility
|
|
588
|
-
// autoConnect: false, // Automatically connect on load
|
|
589
|
-
// showWelcomeMessage: true,
|
|
590
|
-
// welcomeMessage: 'Hello! How can I help you today?'
|
|
591
|
-
// },
|
|
592
|
-
|
|
593
|
-
// Accessibility Configuration
|
|
594
|
-
// accessibility: {
|
|
595
|
-
// ariaLabel: 'Voice Assistant',
|
|
596
|
-
// ariaDescription: 'Click to open voice assistant',
|
|
597
|
-
// keyboardNavigation: true // ESC key to close
|
|
598
|
-
// },
|
|
599
|
-
|
|
600
|
-
// Custom CSS
|
|
601
|
-
// customStyles: `
|
|
602
|
-
// #agent-widget {
|
|
603
|
-
// /* Your custom CSS here */
|
|
604
|
-
// }
|
|
605
|
-
// `,
|
|
606
|
-
|
|
607
|
-
// Variables for your agent/backend
|
|
608
|
-
variables: {
|
|
609
|
-
testMode: true,
|
|
610
|
-
userName: 'Test User',
|
|
611
|
-
page: 'test-agent-app.html'
|
|
612
|
-
}
|
|
613
|
-
});</code></pre></div>
|
|
614
|
-
</div>
|
|
615
|
-
|
|
616
|
-
<script>
|
|
617
|
-
function switchTab(tabName) {
|
|
618
|
-
// Hide all tab contents
|
|
619
|
-
document.querySelectorAll('.tab-content').forEach(content => {
|
|
620
|
-
content.classList.remove('active');
|
|
621
|
-
});
|
|
622
|
-
|
|
623
|
-
// Remove active class from all tabs
|
|
624
|
-
document.querySelectorAll('.tab').forEach(tab => {
|
|
625
|
-
tab.classList.remove('active');
|
|
626
|
-
});
|
|
627
|
-
|
|
628
|
-
// Show selected tab content
|
|
629
|
-
document.getElementById(tabName + '-tab').classList.add('active');
|
|
630
|
-
|
|
631
|
-
// Add active class to clicked tab
|
|
632
|
-
event.target.classList.add('active');
|
|
633
|
-
}
|
|
634
|
-
</script>
|
|
635
|
-
|
|
636
|
-
<h2>Manual Tests:</h2>
|
|
637
|
-
<button onclick="testMicButton()">Test Mic Button Click</button>
|
|
638
|
-
<button onclick="testToggleVoice()">Test ToggleVoice Method</button>
|
|
639
|
-
<button onclick="checkWidgetState()">Check Widget State</button>
|
|
640
|
-
<button onclick="testMicrophone()">Test Microphone Access</button>
|
|
641
|
-
</div>
|
|
642
|
-
|
|
643
|
-
<!-- Load the widget -->
|
|
644
|
-
<script src="../agent-widget.js" onload="console.log('SDK script loaded successfully')" onerror="console.error('Failed to load SDK script')"></script>
|
|
645
|
-
|
|
646
|
-
<script>
|
|
647
|
-
// Override console.log to show in page
|
|
648
|
-
const originalLog = console.log;
|
|
649
|
-
const originalError = console.error;
|
|
650
|
-
const logDiv = document.getElementById('log');
|
|
651
|
-
|
|
652
|
-
function addLog(message, type = 'log') {
|
|
653
|
-
const time = new Date().toLocaleTimeString();
|
|
654
|
-
const color = type === 'error' ? '#EF4444' : '#10B981';
|
|
655
|
-
logDiv.innerHTML += `<div style="color: ${color};">[${time}] ${message}</div>`;
|
|
656
|
-
logDiv.scrollTop = logDiv.scrollHeight;
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
console.log = (...args) => {
|
|
660
|
-
originalLog(...args);
|
|
661
|
-
addLog(args.join(' '));
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
console.error = (...args) => {
|
|
665
|
-
originalError(...args);
|
|
666
|
-
addLog(args.join(' '), 'error');
|
|
667
|
-
};
|
|
668
|
-
|
|
669
|
-
// Update status display
|
|
670
|
-
function updateStatus(message, type = 'info') {
|
|
671
|
-
const statusDiv = document.getElementById('status');
|
|
672
|
-
statusDiv.textContent = message;
|
|
673
|
-
statusDiv.className = 'status ' + type;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
// ============================================
|
|
677
|
-
// CUSTOMIZATION CONTROLS - Declare early
|
|
678
|
-
// ============================================
|
|
679
|
-
// Initialize variable first - MUST be declared before any functions that use it
|
|
680
|
-
let controlRowCount = 0;
|
|
681
|
-
|
|
682
|
-
const componentOptions = {
|
|
683
|
-
'button': {
|
|
684
|
-
label: 'Floating Button',
|
|
685
|
-
properties: {
|
|
686
|
-
'backgroundColor': { type: 'color', label: 'Background Color' },
|
|
687
|
-
'hoverColor': { type: 'color', label: 'Hover Color' },
|
|
688
|
-
'size': { type: 'select', label: 'Size', options: ['small', 'medium', 'large', 'xl'] },
|
|
689
|
-
'shape': { type: 'select', label: 'Shape', options: ['circle', 'square', 'rounded'] }
|
|
690
|
-
}
|
|
691
|
-
},
|
|
692
|
-
'header': {
|
|
693
|
-
label: 'Header',
|
|
694
|
-
properties: {
|
|
695
|
-
'backgroundColor': { type: 'color', label: 'Background Color' },
|
|
696
|
-
'textColor': { type: 'color', label: 'Text Color' },
|
|
697
|
-
'title': { type: 'text', label: 'Title' }
|
|
698
|
-
}
|
|
699
|
-
},
|
|
700
|
-
'panel': {
|
|
701
|
-
label: 'Mic Button',
|
|
702
|
-
properties: {
|
|
703
|
-
'micButtonColor': { type: 'color', label: 'Background Color' },
|
|
704
|
-
'micButtonActiveColor': { type: 'color', label: 'Active Color (Recording)' }
|
|
705
|
-
}
|
|
706
|
-
},
|
|
707
|
-
'micButtonHint': {
|
|
708
|
-
label: 'Mic Button Hint',
|
|
709
|
-
properties: {
|
|
710
|
-
'micButtonHint.text': { type: 'text', label: 'Hint Text (empty to hide)' },
|
|
711
|
-
'micButtonHint.color': { type: 'color', label: 'Text Color' },
|
|
712
|
-
'micButtonHint.fontSize': { type: 'text', label: 'Font Size (e.g., 12px)' }
|
|
713
|
-
}
|
|
714
|
-
},
|
|
715
|
-
'direction': {
|
|
716
|
-
label: 'Text Direction',
|
|
717
|
-
properties: {
|
|
718
|
-
'direction': { type: 'select', label: 'Direction', options: ['ltr', 'rtl'] }
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
};
|
|
722
|
-
|
|
723
|
-
function initializeCustomizationControls() {
|
|
724
|
-
// Add one initial row
|
|
725
|
-
addControlRow();
|
|
726
|
-
|
|
727
|
-
// Set up button event listeners
|
|
728
|
-
const addBtn = document.getElementById('add-control-btn');
|
|
729
|
-
const resetBtn = document.getElementById('reset-defaults-btn');
|
|
730
|
-
if (addBtn) {
|
|
731
|
-
addBtn.addEventListener('click', addControlRow);
|
|
732
|
-
}
|
|
733
|
-
if (resetBtn) {
|
|
734
|
-
resetBtn.addEventListener('click', resetToDefaults);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
function addControlRow() {
|
|
739
|
-
controlRowCount++;
|
|
740
|
-
const controlRows = document.getElementById('control-rows');
|
|
741
|
-
const row = document.createElement('div');
|
|
742
|
-
row.className = 'control-row';
|
|
743
|
-
row.id = `control-row-${controlRowCount}`;
|
|
744
|
-
|
|
745
|
-
// Component selector
|
|
746
|
-
const componentSelect = document.createElement('select');
|
|
747
|
-
componentSelect.id = `component-${controlRowCount}`;
|
|
748
|
-
componentSelect.innerHTML = '<option value="">Select Component</option>';
|
|
749
|
-
Object.keys(componentOptions).forEach(key => {
|
|
750
|
-
const option = document.createElement('option');
|
|
751
|
-
option.value = key;
|
|
752
|
-
option.textContent = componentOptions[key].label;
|
|
753
|
-
componentSelect.appendChild(option);
|
|
754
|
-
});
|
|
755
|
-
componentSelect.onchange = () => updatePropertySelect(controlRowCount);
|
|
756
|
-
|
|
757
|
-
// Property selector (will be populated based on component)
|
|
758
|
-
const propertySelect = document.createElement('select');
|
|
759
|
-
propertySelect.id = `property-${controlRowCount}`;
|
|
760
|
-
propertySelect.innerHTML = '<option value="">Select Property</option>';
|
|
761
|
-
|
|
762
|
-
// Value input (dynamically changes based on property type)
|
|
763
|
-
const valueContainer = document.createElement('div');
|
|
764
|
-
valueContainer.id = `value-container-${controlRowCount}`;
|
|
765
|
-
valueContainer.style.display = 'none';
|
|
766
|
-
|
|
767
|
-
// Action buttons
|
|
768
|
-
const actionContainer = document.createElement('div');
|
|
769
|
-
actionContainer.style.display = 'flex';
|
|
770
|
-
actionContainer.style.gap = '8px';
|
|
771
|
-
|
|
772
|
-
const applyBtn = document.createElement('button');
|
|
773
|
-
applyBtn.textContent = 'Apply';
|
|
774
|
-
applyBtn.onclick = () => applyChange(controlRowCount);
|
|
775
|
-
|
|
776
|
-
const removeBtn = document.createElement('button');
|
|
777
|
-
removeBtn.textContent = 'Remove';
|
|
778
|
-
removeBtn.className = 'remove';
|
|
779
|
-
removeBtn.onclick = () => removeControlRow(controlRowCount);
|
|
780
|
-
|
|
781
|
-
actionContainer.appendChild(applyBtn);
|
|
782
|
-
actionContainer.appendChild(removeBtn);
|
|
783
|
-
|
|
784
|
-
row.appendChild(componentSelect);
|
|
785
|
-
row.appendChild(propertySelect);
|
|
786
|
-
row.appendChild(valueContainer);
|
|
787
|
-
row.appendChild(actionContainer);
|
|
788
|
-
|
|
789
|
-
controlRows.appendChild(row);
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
function updatePropertySelect(rowId) {
|
|
793
|
-
const componentSelect = document.getElementById(`component-${rowId}`);
|
|
794
|
-
const propertySelect = document.getElementById(`property-${rowId}`);
|
|
795
|
-
const valueContainer = document.getElementById(`value-container-${rowId}`);
|
|
796
|
-
|
|
797
|
-
const component = componentSelect.value;
|
|
798
|
-
if (!component) {
|
|
799
|
-
propertySelect.innerHTML = '<option value="">Select Property</option>';
|
|
800
|
-
valueContainer.style.display = 'none';
|
|
801
|
-
valueContainer.innerHTML = '';
|
|
802
|
-
return;
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
// Populate properties
|
|
806
|
-
propertySelect.innerHTML = '<option value="">Select Property</option>';
|
|
807
|
-
const properties = componentOptions[component].properties;
|
|
808
|
-
Object.keys(properties).forEach(key => {
|
|
809
|
-
const option = document.createElement('option');
|
|
810
|
-
option.value = key;
|
|
811
|
-
option.textContent = properties[key].label;
|
|
812
|
-
propertySelect.appendChild(option);
|
|
813
|
-
});
|
|
814
|
-
|
|
815
|
-
propertySelect.onchange = () => updateValueInput(rowId);
|
|
816
|
-
valueContainer.style.display = 'none';
|
|
817
|
-
valueContainer.innerHTML = '';
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
function updateValueInput(rowId) {
|
|
821
|
-
const componentSelect = document.getElementById(`component-${rowId}`);
|
|
822
|
-
const propertySelect = document.getElementById(`property-${rowId}`);
|
|
823
|
-
const valueContainer = document.getElementById(`value-container-${rowId}`);
|
|
824
|
-
|
|
825
|
-
const component = componentSelect.value;
|
|
826
|
-
const property = propertySelect.value;
|
|
827
|
-
|
|
828
|
-
if (!component || !property) {
|
|
829
|
-
valueContainer.style.display = 'none';
|
|
830
|
-
valueContainer.innerHTML = '';
|
|
831
|
-
return;
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
const propConfig = componentOptions[component].properties[property];
|
|
835
|
-
valueContainer.innerHTML = '';
|
|
836
|
-
|
|
837
|
-
if (propConfig.type === 'color') {
|
|
838
|
-
const input = document.createElement('input');
|
|
839
|
-
input.type = 'color';
|
|
840
|
-
input.id = `value-${rowId}`;
|
|
841
|
-
// Set current value from widget
|
|
842
|
-
const currentValue = getCurrentValue(component, property);
|
|
843
|
-
if (currentValue) input.value = rgbToHex(currentValue) || currentValue;
|
|
844
|
-
valueContainer.appendChild(input);
|
|
845
|
-
} else if (propConfig.type === 'select') {
|
|
846
|
-
const select = document.createElement('select');
|
|
847
|
-
select.id = `value-${rowId}`;
|
|
848
|
-
propConfig.options.forEach(opt => {
|
|
849
|
-
const option = document.createElement('option');
|
|
850
|
-
option.value = opt;
|
|
851
|
-
option.textContent = opt.charAt(0).toUpperCase() + opt.slice(1);
|
|
852
|
-
select.appendChild(option);
|
|
853
|
-
});
|
|
854
|
-
// Set current value
|
|
855
|
-
const currentValue = getCurrentValue(component, property);
|
|
856
|
-
if (currentValue !== null && currentValue !== undefined) {
|
|
857
|
-
select.value = currentValue.toString();
|
|
858
|
-
}
|
|
859
|
-
valueContainer.appendChild(select);
|
|
860
|
-
} else if (propConfig.type === 'text') {
|
|
861
|
-
const input = document.createElement('input');
|
|
862
|
-
input.type = 'text';
|
|
863
|
-
input.id = `value-${rowId}`;
|
|
864
|
-
input.placeholder = 'Enter value';
|
|
865
|
-
// Set current value
|
|
866
|
-
const currentValue = getCurrentValue(component, property);
|
|
867
|
-
if (currentValue !== null && currentValue !== undefined) {
|
|
868
|
-
input.value = currentValue;
|
|
869
|
-
}
|
|
870
|
-
valueContainer.appendChild(input);
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
valueContainer.style.display = 'block';
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
function getCurrentValue(component, property) {
|
|
877
|
-
if (!window.testWidget) return null;
|
|
878
|
-
const config = window.testWidget.config;
|
|
879
|
-
|
|
880
|
-
if (component === 'button' && config.button) {
|
|
881
|
-
return config.button[property];
|
|
882
|
-
} else if (component === 'header' && config.header) {
|
|
883
|
-
return config.header[property];
|
|
884
|
-
} else if (component === 'panel' && config.panel) {
|
|
885
|
-
return config.panel[property];
|
|
886
|
-
} else if (component === 'micButtonHint' && config.panel?.micButtonHint) {
|
|
887
|
-
// Handle nested micButtonHint properties
|
|
888
|
-
const hintKey = property.split('.')[1]; // e.g., 'text', 'color', 'fontSize'
|
|
889
|
-
const value = config.panel.micButtonHint[hintKey];
|
|
890
|
-
return value;
|
|
891
|
-
} else if (component === 'direction') {
|
|
892
|
-
return config.direction;
|
|
893
|
-
}
|
|
894
|
-
return null;
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
function applyChange(rowId) {
|
|
898
|
-
const componentSelect = document.getElementById(`component-${rowId}`);
|
|
899
|
-
const propertySelect = document.getElementById(`property-${rowId}`);
|
|
900
|
-
const valueInput = document.getElementById(`value-${rowId}`);
|
|
901
|
-
|
|
902
|
-
const component = componentSelect.value;
|
|
903
|
-
const property = propertySelect.value;
|
|
904
|
-
let value = valueInput.value;
|
|
905
|
-
|
|
906
|
-
if (!component || !property) {
|
|
907
|
-
alert('Please select component and property');
|
|
908
|
-
return;
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
// Allow empty value for text fields (to hide hint)
|
|
912
|
-
if (value === undefined || value === null) {
|
|
913
|
-
value = '';
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
if (!window.testWidget) {
|
|
917
|
-
alert('Widget not initialized');
|
|
918
|
-
return;
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
// Handle boolean values (only for non-empty values)
|
|
922
|
-
if (value && value !== '') {
|
|
923
|
-
if (value === 'true') value = true;
|
|
924
|
-
if (value === 'false') value = false;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
// Prepare update config
|
|
928
|
-
const updateConfig = {};
|
|
929
|
-
if (component === 'button') {
|
|
930
|
-
updateConfig.button = { [property]: value };
|
|
931
|
-
} else if (component === 'header') {
|
|
932
|
-
updateConfig.header = { [property]: value };
|
|
933
|
-
} else if (component === 'panel') {
|
|
934
|
-
updateConfig.panel = { [property]: value };
|
|
935
|
-
} else if (component === 'micButtonHint') {
|
|
936
|
-
// Handle nested micButtonHint properties
|
|
937
|
-
const hintKey = property.split('.')[1]; // e.g., 'text', 'color', 'fontSize', 'show'
|
|
938
|
-
if (!updateConfig.panel) updateConfig.panel = {};
|
|
939
|
-
if (!updateConfig.panel.micButtonHint) updateConfig.panel.micButtonHint = {};
|
|
940
|
-
updateConfig.panel.micButtonHint[hintKey] = value;
|
|
941
|
-
} else if (component === 'direction') {
|
|
942
|
-
updateConfig.direction = value;
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
// Apply update
|
|
946
|
-
console.log(`Applying change: ${component}.${property} = ${value}`);
|
|
947
|
-
window.testWidget.updateConfig(updateConfig);
|
|
948
|
-
|
|
949
|
-
// Update the displayed code blocks
|
|
950
|
-
updateCodeDisplay();
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
function removeControlRow(rowId) {
|
|
954
|
-
const row = document.getElementById(`control-row-${rowId}`);
|
|
955
|
-
if (row) row.remove();
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
function resetToDefaults() {
|
|
959
|
-
if (!window.testWidget || !window.defaultConfig) {
|
|
960
|
-
alert('Widget or defaults not available');
|
|
961
|
-
return;
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
if (confirm('Reset widget to default configuration?')) {
|
|
965
|
-
window.testWidget.updateConfig(window.defaultConfig);
|
|
966
|
-
updateCodeDisplay();
|
|
967
|
-
|
|
968
|
-
// Clear all control rows
|
|
969
|
-
const controlRows = document.getElementById('control-rows');
|
|
970
|
-
controlRows.innerHTML = '';
|
|
971
|
-
controlRowCount = 0;
|
|
972
|
-
addControlRow();
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
function updateCodeDisplay() {
|
|
977
|
-
if (!window.testWidget) return;
|
|
978
|
-
const config = window.testWidget.config;
|
|
979
|
-
|
|
980
|
-
// Helper to safely get position value
|
|
981
|
-
function getPositionValue() {
|
|
982
|
-
if (!config.position) return 'bottom-right';
|
|
983
|
-
if (typeof config.position === 'string') return config.position;
|
|
984
|
-
// If it's an object, extract the string representation
|
|
985
|
-
return `${config.position.vertical || 'bottom'}-${config.position.horizontal || 'right'}`;
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
// Update simple tab
|
|
989
|
-
const simpleCode = document.querySelector('#simple-tab code');
|
|
990
|
-
if (simpleCode) {
|
|
991
|
-
const position = getPositionValue();
|
|
992
|
-
simpleCode.textContent = `const widget = new TTPAgentSDK.AgentWidget({
|
|
993
|
-
agentId: 'agent_87c4a55a1',
|
|
994
|
-
appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC',
|
|
995
|
-
|
|
996
|
-
primaryColor: '${config.primaryColor || '#10B981'}',
|
|
997
|
-
position: '${position}',
|
|
998
|
-
|
|
999
|
-
icon: {
|
|
1000
|
-
type: '${config.icon?.type || 'custom'}',
|
|
1001
|
-
customImage: '${config.icon?.customImage || 'https://talktopc.com/logo192.png'}',
|
|
1002
|
-
size: '${config.icon?.size || 'medium'}'
|
|
1003
|
-
},
|
|
1004
|
-
|
|
1005
|
-
button: {
|
|
1006
|
-
backgroundColor: '${config.button?.backgroundColor || '#FFFFFF'}',
|
|
1007
|
-
hoverColor: '${config.button?.hoverColor || '#E5E7EB'}'
|
|
1008
|
-
},
|
|
1009
|
-
|
|
1010
|
-
header: {
|
|
1011
|
-
title: '${(config.header?.title || 'TTP Support').replace(/'/g, "\\'")}',
|
|
1012
|
-
backgroundColor: '${config.header?.backgroundColor || '#A78BFA'}',
|
|
1013
|
-
textColor: '${config.header?.textColor || '#FFFFFF'}'
|
|
1014
|
-
},
|
|
1015
|
-
|
|
1016
|
-
panel: {
|
|
1017
|
-
micButtonColor: '${config.panel?.micButtonColor || '#E5E7EB'}',
|
|
1018
|
-
micButtonActiveColor: '${config.panel?.micButtonActiveColor || '#EF4444'}'
|
|
1019
|
-
}
|
|
1020
|
-
});`;
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
function rgbToHex(rgb) {
|
|
1025
|
-
if (!rgb) return null;
|
|
1026
|
-
if (rgb.startsWith('#')) return rgb;
|
|
1027
|
-
// Try to parse rgb/rgba format
|
|
1028
|
-
const match = rgb.match(/\d+/g);
|
|
1029
|
-
if (match && match.length >= 3) {
|
|
1030
|
-
return '#' + match.slice(0, 3).map(x => {
|
|
1031
|
-
const hex = parseInt(x).toString(16);
|
|
1032
|
-
return hex.length === 1 ? '0' + hex : hex;
|
|
1033
|
-
}).join('');
|
|
1034
|
-
}
|
|
1035
|
-
return null;
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
// Initialize the widget
|
|
1039
|
-
try {
|
|
1040
|
-
console.log('Initializing widget with agent ID + app ID...');
|
|
1041
|
-
console.log('TTPAgentSDK available:', typeof TTPAgentSDK);
|
|
1042
|
-
console.log('TTPAgentSDK.AgentWidget available:', typeof TTPAgentSDK?.AgentWidget);
|
|
1043
|
-
|
|
1044
|
-
if (typeof TTPAgentSDK === 'undefined') {
|
|
1045
|
-
throw new Error('TTPAgentSDK is not defined. Check if the script loaded correctly.');
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
if (typeof TTPAgentSDK.AgentWidget === 'undefined') {
|
|
1049
|
-
throw new Error('TTPAgentSDK.AgentWidget is not defined. Check the SDK build.');
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
// Create a new AgentWidget instance with agent ID + app ID
|
|
1053
|
-
// getSessionUrl is now OPTIONAL - widget will auto-construct URL from agentId/appId
|
|
1054
|
-
const widget = new TTPAgentSDK.AgentWidget({
|
|
1055
|
-
agentId: 'agent_87c4a55a1',
|
|
1056
|
-
appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC',
|
|
1057
|
-
|
|
1058
|
-
// getSessionUrl is OPTIONAL - omitted here, so widget auto-constructs the WebSocket URL
|
|
1059
|
-
// If you need signed links or custom URL logic, you can provide it:
|
|
1060
|
-
// getSessionUrl: async ({ agentId, appId, variables }) => { ... }
|
|
1061
|
-
|
|
1062
|
-
// Optional: Pass variables for your agent/backend
|
|
1063
|
-
variables: {
|
|
1064
|
-
testMode: true,
|
|
1065
|
-
userName: 'Test User',
|
|
1066
|
-
page: 'test-agent-app.html',
|
|
1067
|
-
connectionType: 'direct'
|
|
1068
|
-
},
|
|
1069
|
-
|
|
1070
|
-
// Customize appearance (using simple config - backward compatible)
|
|
1071
|
-
primaryColor: '#10B981',
|
|
1072
|
-
position: 'bottom-right',
|
|
1073
|
-
|
|
1074
|
-
// Set TTP icon
|
|
1075
|
-
icon: {
|
|
1076
|
-
type: 'custom',
|
|
1077
|
-
customImage: 'https://talktopc.com/logo192.png',
|
|
1078
|
-
size: 'medium'
|
|
1079
|
-
},
|
|
1080
|
-
|
|
1081
|
-
// Button colors - Floating button (main button) - WHITE
|
|
1082
|
-
button: {
|
|
1083
|
-
backgroundColor: '#FFFFFF', // White background for floating button
|
|
1084
|
-
hoverColor: '#E5E7EB' // Gray on hover
|
|
1085
|
-
},
|
|
1086
|
-
|
|
1087
|
-
// Header colors - Top of panel - LIGHT PURPLE
|
|
1088
|
-
header: {
|
|
1089
|
-
title: 'TTP Support',
|
|
1090
|
-
backgroundColor: '#A78BFA', // Light purple header background
|
|
1091
|
-
textColor: '#FFFFFF' // White text
|
|
1092
|
-
},
|
|
1093
|
-
|
|
1094
|
-
// Panel colors - Mic button inside panel - GRAY
|
|
1095
|
-
panel: {
|
|
1096
|
-
micButtonColor: '#E5E7EB', // Gray mic button
|
|
1097
|
-
micButtonActiveColor: '#EF4444' // Red when active/recording
|
|
1098
|
-
},
|
|
1099
|
-
|
|
1100
|
-
// Behavior: new options
|
|
1101
|
-
behavior: {
|
|
1102
|
-
startOpen: true, // Start with panel open on page load
|
|
1103
|
-
hidden: false, // If true, hides the floating button
|
|
1104
|
-
autoConnect: false,
|
|
1105
|
-
showWelcomeMessage: true,
|
|
1106
|
-
welcomeMessage: 'Hello! How can I help you today?'
|
|
1107
|
-
},
|
|
1108
|
-
|
|
1109
|
-
// Enhanced features are now available but using defaults
|
|
1110
|
-
// You can optionally add:
|
|
1111
|
-
// button: { size: 'large', shape: 'circle' },
|
|
1112
|
-
// panel: { width: 400, height: 600 },
|
|
1113
|
-
// header: { title: 'My Voice Assistant' },
|
|
1114
|
-
// animation: { enableHover: true, enablePulse: true }
|
|
1115
|
-
});
|
|
1116
|
-
|
|
1117
|
-
// Store widget reference for testing (like the working implementation)
|
|
1118
|
-
window.testWidget = widget;
|
|
1119
|
-
|
|
1120
|
-
// Store default config for reset functionality (matches initial widget config)
|
|
1121
|
-
window.defaultConfig = JSON.parse(JSON.stringify({
|
|
1122
|
-
primaryColor: '#10B981',
|
|
1123
|
-
position: 'bottom-right',
|
|
1124
|
-
direction: 'ltr',
|
|
1125
|
-
icon: {
|
|
1126
|
-
type: 'custom',
|
|
1127
|
-
customImage: 'https://talktopc.com/logo192.png',
|
|
1128
|
-
size: 'medium'
|
|
1129
|
-
},
|
|
1130
|
-
button: {
|
|
1131
|
-
backgroundColor: '#FFFFFF',
|
|
1132
|
-
hoverColor: '#E5E7EB',
|
|
1133
|
-
size: 'medium',
|
|
1134
|
-
shape: 'circle'
|
|
1135
|
-
},
|
|
1136
|
-
header: {
|
|
1137
|
-
title: 'TTP Support',
|
|
1138
|
-
backgroundColor: '#A78BFA',
|
|
1139
|
-
textColor: '#FFFFFF'
|
|
1140
|
-
},
|
|
1141
|
-
panel: {
|
|
1142
|
-
micButtonColor: '#E5E7EB',
|
|
1143
|
-
micButtonActiveColor: '#EF4444',
|
|
1144
|
-
micButtonHint: {
|
|
1145
|
-
text: 'Click the button to start voice conversation',
|
|
1146
|
-
color: '#6B7280',
|
|
1147
|
-
fontSize: '12px'
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
}));
|
|
1151
|
-
|
|
1152
|
-
// Initialize customization controls
|
|
1153
|
-
initializeCustomizationControls();
|
|
1154
|
-
|
|
1155
|
-
console.log('Widget initialized successfully with agent ID + app ID!');
|
|
1156
|
-
console.log('Widget instance:', widget);
|
|
1157
|
-
console.log('Test methods available at window.testWidget');
|
|
1158
|
-
updateStatus('Widget loaded and ready ✓', 'success');
|
|
1159
|
-
|
|
1160
|
-
} catch (error) {
|
|
1161
|
-
console.error('Failed to initialize widget:', error);
|
|
1162
|
-
updateStatus('Widget failed to load ✗', 'error');
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
// Test functions (matching the working implementation)
|
|
1166
|
-
function testMicButton() {
|
|
1167
|
-
console.log('🎤 Testing mic button manually...');
|
|
1168
|
-
const micButton = document.getElementById('agent-mic-button');
|
|
1169
|
-
if (micButton) {
|
|
1170
|
-
console.log('🎤 Found mic button, clicking...');
|
|
1171
|
-
micButton.click();
|
|
1172
|
-
} else {
|
|
1173
|
-
console.log('🎤 Mic button not found');
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
function testToggleVoice() {
|
|
1178
|
-
console.log('🎤 Testing toggleVoice method...');
|
|
1179
|
-
if (window.testWidget && window.testWidget.toggleVoice) {
|
|
1180
|
-
window.testWidget.toggleVoice();
|
|
1181
|
-
} else {
|
|
1182
|
-
console.log('🎤 toggleVoice method not available');
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
function checkWidgetState() {
|
|
1187
|
-
console.log('🎤 Widget state:', {
|
|
1188
|
-
isActive: window.testWidget?.isActive,
|
|
1189
|
-
isOpen: window.testWidget?.isOpen,
|
|
1190
|
-
sdk: window.testWidget?.sdk
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
async function testMicrophone() {
|
|
1195
|
-
console.log('Testing microphone access...');
|
|
1196
|
-
try {
|
|
1197
|
-
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
1198
|
-
console.log('Microphone access granted ✓');
|
|
1199
|
-
stream.getTracks().forEach(track => track.stop());
|
|
1200
|
-
alert('Microphone access OK!');
|
|
1201
|
-
} catch (error) {
|
|
1202
|
-
console.error('Microphone access denied:', error);
|
|
1203
|
-
alert('Microphone access DENIED! Please allow microphone in browser settings.');
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1207
|
-
</script>
|
|
1208
|
-
</body>
|
|
1209
|
-
</html>
|