ttp-agent-sdk 2.34.14 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ENHANCED_WIDGET_GUIDE.md +5 -32
- package/GETTING_STARTED.md +20 -73
- package/README.md +14 -38
- package/WORDPRESS_WIX_GUIDE.md +8 -18
- package/dist/agent-widget.dev.js +388 -274
- package/dist/agent-widget.dev.js.map +1 -1
- package/dist/agent-widget.esm.js +1 -1
- package/dist/agent-widget.esm.js.map +1 -1
- package/dist/agent-widget.js +1 -1
- package/dist/agent-widget.js.map +1 -1
- package/dist/examples/test-text-chat.html +2 -26
- package/dist/index.html +169 -439
- package/examples/test-text-chat.html +2 -26
- package/package.json +2 -2
- package/SIGNED_LINK_GUIDE.md +0 -249
- package/dist/examples/test-signed-link.html +0 -503
- package/examples/test-signed-link.html +0 -503
package/dist/index.html
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
<img src="https://talktopc.com/logo192.png" alt="TTP Logo" style="width: 40px; height: 40px; border-radius: 8px;">
|
|
24
24
|
<div>
|
|
25
25
|
<h1 style="margin: 0; font-size: 1.4rem;">TTP Agent SDK</h1>
|
|
26
|
-
<p class="version" style="margin: 0;">v2.
|
|
26
|
+
<p class="version" style="margin: 0;">v2.34.9</p>
|
|
27
27
|
</div>
|
|
28
28
|
</div>
|
|
29
29
|
</div>
|
|
@@ -157,8 +157,8 @@
|
|
|
157
157
|
<div class="feature-compact-item">
|
|
158
158
|
<span class="feature-compact-icon">🔒</span>
|
|
159
159
|
<div>
|
|
160
|
-
<strong>
|
|
161
|
-
<p>
|
|
160
|
+
<strong>Simple Authentication</strong>
|
|
161
|
+
<p>Direct connection using agentId and appId with domain whitelist access control</p>
|
|
162
162
|
</div>
|
|
163
163
|
</div>
|
|
164
164
|
<div class="feature-compact-item">
|
|
@@ -228,38 +228,14 @@ const sdk = new window.TTPAgentSDK.VoiceSDK(config);</code></pre>
|
|
|
228
228
|
|
|
229
229
|
<div class="step-card">
|
|
230
230
|
<div class="step-number">1</div>
|
|
231
|
-
<div class="step-content">
|
|
232
|
-
<h3>Get a Signed URL</h3>
|
|
233
|
-
<div class="warning-box">
|
|
234
|
-
<strong>🔒 Backend-to-Backend:</strong> Your frontend requests from YOUR backend, which then communicates with TTP backend. Never expose your API key to the frontend!
|
|
235
|
-
</div>
|
|
236
|
-
<p><strong>Frontend → Your Backend:</strong></p>
|
|
237
|
-
<pre><code>const response = await fetch('/api/get-voice-session', {
|
|
238
|
-
method: 'POST',
|
|
239
|
-
headers: {
|
|
240
|
-
'Content-Type': 'application/json'
|
|
241
|
-
},
|
|
242
|
-
body: JSON.stringify({
|
|
243
|
-
agentId: 'agent_123'
|
|
244
|
-
})
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
const { signedUrl } = await response.json();</code></pre>
|
|
248
|
-
<p><strong>Your Backend → TTP Backend:</strong> (See Authentication section for details)</p>
|
|
249
|
-
</div>
|
|
250
|
-
</div>
|
|
251
|
-
|
|
252
|
-
<div class="step-card">
|
|
253
|
-
<div class="step-number">2</div>
|
|
254
231
|
<div class="step-content">
|
|
255
232
|
<h3>Initialize the SDK</h3>
|
|
256
|
-
<p>Create a VoiceSDK instance with
|
|
233
|
+
<p>Create a VoiceSDK instance with your agent ID and app ID:</p>
|
|
257
234
|
<pre><code>import { VoiceSDK } from 'ttp-agent-sdk';
|
|
258
235
|
|
|
259
236
|
const voiceSDK = new VoiceSDK({
|
|
260
|
-
signedUrl: signedUrl, // signedUrl from step 1
|
|
261
|
-
appId: 'your_app_id', // Your application ID
|
|
262
237
|
agentId: 'agent_123', // The AI agent to connect to
|
|
238
|
+
appId: 'your_app_id', // Your application ID
|
|
263
239
|
|
|
264
240
|
// Optional: Configure audio formats (v2 protocol)
|
|
265
241
|
outputContainer: 'raw', // 'raw' or 'wav'
|
|
@@ -287,7 +263,7 @@ voiceSDK.on('message', (msg) => {
|
|
|
287
263
|
</div>
|
|
288
264
|
|
|
289
265
|
<div class="step-card">
|
|
290
|
-
<div class="step-number">
|
|
266
|
+
<div class="step-number">2</div>
|
|
291
267
|
<div class="step-content">
|
|
292
268
|
<h3>Connect & Start Recording</h3>
|
|
293
269
|
<p>Connect to the agent and start capturing audio:</p>
|
|
@@ -306,203 +282,26 @@ await voiceSDK.stopRecording();</code></pre>
|
|
|
306
282
|
<!-- Authentication -->
|
|
307
283
|
<section id="authentication" class="doc-section">
|
|
308
284
|
<h1>Authentication</h1>
|
|
309
|
-
<p>
|
|
285
|
+
<p>The SDK connects directly using <code>agentId</code> and <code>appId</code>. No server-side authentication step is needed. Access control is managed via domain whitelist in your agent's admin panel.</p>
|
|
310
286
|
|
|
287
|
+
<h2>How It Works</h2>
|
|
311
288
|
<div class="info-box">
|
|
312
|
-
<strong
|
|
313
|
-
</div>
|
|
314
|
-
|
|
315
|
-
<h2>Authentication Flow</h2>
|
|
316
|
-
<div class="warning-box">
|
|
317
|
-
<strong>🔐 Critical Security Note:</strong> The signed URL generation happens <strong>Backend-to-Backend</strong>. Your frontend NEVER directly contacts TTP backend. This protects your API key!
|
|
318
|
-
</div>
|
|
319
|
-
<div class="flow-diagram">
|
|
320
|
-
<div class="flow-step">
|
|
321
|
-
<div class="flow-box" style="background: linear-gradient(135deg, #e0f2fe 0%, #bfdbfe 100%);">
|
|
322
|
-
<strong>1. 🖥️ Your Frontend</strong>
|
|
323
|
-
<p>User clicks "Start Voice Chat"</p>
|
|
324
|
-
</div>
|
|
325
|
-
<div class="flow-arrow">↓</div>
|
|
326
|
-
<div class="flow-box" style="background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);">
|
|
327
|
-
<strong>2. 🔧 Your Backend</strong>
|
|
328
|
-
<p>Receives: POST /api/get-voice-session</p>
|
|
329
|
-
</div>
|
|
330
|
-
<div class="flow-arrow">↓ 🔒 Backend-to-Backend (API Key)</div>
|
|
331
|
-
<div class="flow-box" style="background: linear-gradient(135deg, #e9d5ff 0%, #d8b4fe 100%);">
|
|
332
|
-
<strong>3. 🏢 TTP Backend</strong>
|
|
333
|
-
<p>Validates API key & generates signed JWT</p>
|
|
334
|
-
</div>
|
|
335
|
-
<div class="flow-arrow">↑ Returns signed URL</div>
|
|
336
|
-
<div class="flow-box" style="background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);">
|
|
337
|
-
<strong>4. 🔧 Your Backend</strong>
|
|
338
|
-
<p>Forwards signed URL to frontend</p>
|
|
339
|
-
</div>
|
|
340
|
-
<div class="flow-arrow">↓</div>
|
|
341
|
-
<div class="flow-box" style="background: linear-gradient(135deg, #e0f2fe 0%, #bfdbfe 100%);">
|
|
342
|
-
<strong>5. 🖥️ Your Frontend</strong>
|
|
343
|
-
<p>Uses SDK with signed URL (WebSocket)</p>
|
|
344
|
-
</div>
|
|
345
|
-
</div>
|
|
346
|
-
</div>
|
|
347
|
-
|
|
348
|
-
<h2>Backend Implementation (Backend-to-Backend)</h2>
|
|
349
|
-
<p><strong>Your backend acts as a secure proxy between your frontend and TTP backend:</strong></p>
|
|
350
|
-
|
|
351
|
-
<div class="info-box">
|
|
352
|
-
<strong>💡 Architecture:</strong> Frontend → Your Backend → TTP Backend → Your Backend → Frontend
|
|
289
|
+
<strong>💡 Simple Setup:</strong> Just provide your <code>agentId</code> and <code>appId</code> in the SDK configuration. The SDK connects directly to the TTP backend via WebSocket.
|
|
353
290
|
</div>
|
|
354
291
|
|
|
355
|
-
<
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
<strong>Examples:</strong>
|
|
359
|
-
<ul style="margin-top: 10px; margin-left: 20px;">
|
|
360
|
-
<li>5 minutes: <code>300000</code></li>
|
|
361
|
-
<li>1 hour (default): <code>3600000</code></li>
|
|
362
|
-
<li>24 hours: <code>86400000</code></li>
|
|
363
|
-
</ul>
|
|
364
|
-
</div>
|
|
365
|
-
|
|
366
|
-
<pre><code>// Example: Node.js/Express
|
|
367
|
-
// This endpoint is called by YOUR FRONTEND
|
|
368
|
-
app.post('/api/get-voice-session', async (req, res) => {
|
|
369
|
-
const { agentId } = req.body;
|
|
370
|
-
|
|
371
|
-
// 1️⃣ Authenticate YOUR user (your auth logic)
|
|
372
|
-
if (!req.user) {
|
|
373
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// 2️⃣ Backend-to-Backend: Call TTP Backend with YOUR API Key
|
|
377
|
-
// ⚠️ This happens SERVER-SIDE only - API key never exposed to frontend
|
|
378
|
-
const response = await fetch('https://backend.talktopc.com/api/public/agents/signed-url', {
|
|
379
|
-
method: 'POST',
|
|
380
|
-
headers: {
|
|
381
|
-
'Content-Type': 'application/json',
|
|
382
|
-
'Authorization': `Bearer ${process.env.TTP_API_KEY}` // 🔒 Secret - never in frontend!
|
|
383
|
-
},
|
|
384
|
-
body: JSON.stringify({
|
|
385
|
-
agentId: agentId,
|
|
386
|
-
appId: process.env.TTP_APP_ID,
|
|
387
|
-
expirationMs: 3600000, // Optional: Token TTL in milliseconds (default: 1 hour)
|
|
388
|
-
allowOverride: true // Optional: Enable agent settings override (default: false)
|
|
389
|
-
})
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
const { signedLink } = await response.json();
|
|
393
|
-
|
|
394
|
-
// 3️⃣ Return signed URL to YOUR frontend
|
|
395
|
-
res.json({ signedUrl: signedLink });
|
|
292
|
+
<pre><code>const voiceSDK = new VoiceSDK({
|
|
293
|
+
agentId: 'agent_123', // Your AI agent ID
|
|
294
|
+
appId: 'your_app_id' // Your application ID
|
|
396
295
|
});</code></pre>
|
|
397
296
|
|
|
398
|
-
<
|
|
399
|
-
|
|
297
|
+
<h2>Domain Whitelist</h2>
|
|
298
|
+
<p>To control which websites can use your agent, configure a domain whitelist in your agent's admin panel. Only requests originating from whitelisted domains will be accepted.</p>
|
|
299
|
+
|
|
300
|
+
<div class="info-box">
|
|
301
|
+
<strong>💡 Tip:</strong> During development, you can add <code>localhost</code> to the domain whitelist. Remove it before deploying to production.
|
|
400
302
|
</div>
|
|
401
303
|
|
|
402
|
-
<h2>
|
|
403
|
-
<p>The signed URL endpoint returns the following response:</p>
|
|
404
|
-
<pre><code>{
|
|
405
|
-
"signedLink": "wss://speech.talktopc.com/ws/conv?signed_token=eyJ...",
|
|
406
|
-
"agentId": "agent_123",
|
|
407
|
-
"userId": "user_789",
|
|
408
|
-
"appId": "your_app_id",
|
|
409
|
-
"expiresAt": "2025-11-11T21:00:00.000+00:00",
|
|
410
|
-
"expiresIn": 3600000,
|
|
411
|
-
"generatedAt": "2025-11-11T20:00:00.000+00:00",
|
|
412
|
-
"availableCredits": 150.5,
|
|
413
|
-
"authenticationStatus": "SUCCESS"
|
|
414
|
-
}</code></pre>
|
|
415
|
-
|
|
416
|
-
<table class="properties-table">
|
|
417
|
-
<thead>
|
|
418
|
-
<tr>
|
|
419
|
-
<th>Property</th>
|
|
420
|
-
<th>Type</th>
|
|
421
|
-
<th>Description</th>
|
|
422
|
-
</tr>
|
|
423
|
-
</thead>
|
|
424
|
-
<tbody>
|
|
425
|
-
<tr>
|
|
426
|
-
<td><code>signedLink</code></td>
|
|
427
|
-
<td>string</td>
|
|
428
|
-
<td>The WebSocket URL with signed JWT token</td>
|
|
429
|
-
</tr>
|
|
430
|
-
<tr>
|
|
431
|
-
<td><code>agentId</code></td>
|
|
432
|
-
<td>string</td>
|
|
433
|
-
<td>The AI agent identifier</td>
|
|
434
|
-
</tr>
|
|
435
|
-
<tr>
|
|
436
|
-
<td><code>userId</code></td>
|
|
437
|
-
<td>string</td>
|
|
438
|
-
<td>Your user's identifier (ttpId)</td>
|
|
439
|
-
</tr>
|
|
440
|
-
<tr>
|
|
441
|
-
<td><code>appId</code></td>
|
|
442
|
-
<td>string</td>
|
|
443
|
-
<td>Your application identifier</td>
|
|
444
|
-
</tr>
|
|
445
|
-
<tr>
|
|
446
|
-
<td><code>expiresAt</code></td>
|
|
447
|
-
<td>Date</td>
|
|
448
|
-
<td>When the signed URL expires (ISO 8601 format)</td>
|
|
449
|
-
</tr>
|
|
450
|
-
<tr>
|
|
451
|
-
<td><code>expiresIn</code></td>
|
|
452
|
-
<td>number</td>
|
|
453
|
-
<td>Token validity duration in milliseconds</td>
|
|
454
|
-
</tr>
|
|
455
|
-
<tr>
|
|
456
|
-
<td><code>generatedAt</code></td>
|
|
457
|
-
<td>Date</td>
|
|
458
|
-
<td>When the signed URL was generated (ISO 8601 format)</td>
|
|
459
|
-
</tr>
|
|
460
|
-
<tr>
|
|
461
|
-
<td><code>availableCredits</code></td>
|
|
462
|
-
<td>number</td>
|
|
463
|
-
<td>User's remaining credit balance</td>
|
|
464
|
-
</tr>
|
|
465
|
-
<tr>
|
|
466
|
-
<td><code>authenticationStatus</code></td>
|
|
467
|
-
<td>string</td>
|
|
468
|
-
<td>Always "SUCCESS" for successful requests</td>
|
|
469
|
-
</tr>
|
|
470
|
-
</tbody>
|
|
471
|
-
</table>
|
|
472
|
-
|
|
473
|
-
<h2>JWT Token Properties</h2>
|
|
474
|
-
<table class="properties-table">
|
|
475
|
-
<thead>
|
|
476
|
-
<tr>
|
|
477
|
-
<th>Property</th>
|
|
478
|
-
<th>Description</th>
|
|
479
|
-
</tr>
|
|
480
|
-
</thead>
|
|
481
|
-
<tbody>
|
|
482
|
-
<tr>
|
|
483
|
-
<td><code>agentId</code></td>
|
|
484
|
-
<td>The AI agent identifier</td>
|
|
485
|
-
</tr>
|
|
486
|
-
<tr>
|
|
487
|
-
<td><code>userId</code></td>
|
|
488
|
-
<td>Your user's identifier</td>
|
|
489
|
-
</tr>
|
|
490
|
-
<tr>
|
|
491
|
-
<td><code>appId</code></td>
|
|
492
|
-
<td>Your application identifier</td>
|
|
493
|
-
</tr>
|
|
494
|
-
<tr>
|
|
495
|
-
<td><code>allowOverride</code></td>
|
|
496
|
-
<td>Permission flag for agent settings override (optional)</td>
|
|
497
|
-
</tr>
|
|
498
|
-
<tr>
|
|
499
|
-
<td><code>exp</code></td>
|
|
500
|
-
<td>Token expiration time (TTL - configurable via <code>expirationMs</code>, defaults to 1 hour)</td>
|
|
501
|
-
</tr>
|
|
502
|
-
</tbody>
|
|
503
|
-
</table>
|
|
504
|
-
|
|
505
|
-
<h2>Request Parameters</h2>
|
|
304
|
+
<h2>Configuration Parameters</h2>
|
|
506
305
|
<table class="properties-table">
|
|
507
306
|
<thead>
|
|
508
307
|
<tr>
|
|
@@ -525,18 +324,6 @@ app.post('/api/get-voice-session', async (req, res) => {
|
|
|
525
324
|
<td>Yes</td>
|
|
526
325
|
<td>Your application identifier</td>
|
|
527
326
|
</tr>
|
|
528
|
-
<tr>
|
|
529
|
-
<td><code>expirationMs</code></td>
|
|
530
|
-
<td>number</td>
|
|
531
|
-
<td>No</td>
|
|
532
|
-
<td>Token TTL in milliseconds (default: 3600000 = 1 hour)</td>
|
|
533
|
-
</tr>
|
|
534
|
-
<tr>
|
|
535
|
-
<td><code>allowOverride</code></td>
|
|
536
|
-
<td>boolean</td>
|
|
537
|
-
<td>No</td>
|
|
538
|
-
<td>Enable agent settings override permission (default: false)</td>
|
|
539
|
-
</tr>
|
|
540
327
|
</tbody>
|
|
541
328
|
</table>
|
|
542
329
|
</section>
|
|
@@ -548,25 +335,21 @@ app.post('/api/get-voice-session', async (req, res) => {
|
|
|
548
335
|
<p>Dynamically customize agent behavior, voice, and personality on a per-session basis.</p>
|
|
549
336
|
|
|
550
337
|
<div class="info-box">
|
|
551
|
-
<strong
|
|
338
|
+
<strong>💡 Access Control:</strong> Agent settings override is available when the agent has domain whitelist configured in the admin panel. No additional authentication step is required.
|
|
552
339
|
</div>
|
|
553
340
|
|
|
554
341
|
<h2>How It Works</h2>
|
|
555
|
-
<div class="info-box">
|
|
556
|
-
<strong>🔐 Backend-to-Backend First:</strong> The signed URL with override permission is obtained via backend-to-backend communication before your frontend can use it.
|
|
557
|
-
</div>
|
|
558
342
|
<ol class="numbered-list">
|
|
559
|
-
<li><strong>
|
|
560
|
-
<li><strong>
|
|
561
|
-
<li><strong>
|
|
562
|
-
<li><strong>TTP Backend:</strong> Validates the
|
|
343
|
+
<li><strong>Configure:</strong> Set up a domain whitelist for your agent in the admin panel</li>
|
|
344
|
+
<li><strong>Initialize:</strong> Pass <code>agentSettingsOverride</code> in the SDK configuration</li>
|
|
345
|
+
<li><strong>Connect:</strong> The SDK sends overrides in the hello message</li>
|
|
346
|
+
<li><strong>TTP Backend:</strong> Validates the domain and applies your overrides</li>
|
|
563
347
|
</ol>
|
|
564
348
|
|
|
565
349
|
<h2>Example</h2>
|
|
566
350
|
<pre><code>const voiceSDK = new VoiceSDK({
|
|
567
|
-
signedUrl: signedUrl, // signedUrl from your backend
|
|
568
|
-
appId: 'your_app_id', // Your application ID
|
|
569
351
|
agentId: 'agent_123', // The AI agent to connect to
|
|
352
|
+
appId: 'your_app_id', // Your application ID
|
|
570
353
|
|
|
571
354
|
// Override agent settings
|
|
572
355
|
agentSettingsOverride: {
|
|
@@ -649,16 +432,7 @@ app.post('/api/get-voice-session', async (req, res) => {
|
|
|
649
432
|
<p>When using VoiceSDK v2, variables are passed in the SDK constructor:</p>
|
|
650
433
|
<pre><code>import { VoiceSDK_v2 } from 'ttp-agent-sdk';
|
|
651
434
|
|
|
652
|
-
// Get signed URL from your backend first
|
|
653
|
-
const response = await fetch('/api/get-voice-session', {
|
|
654
|
-
method: 'POST',
|
|
655
|
-
headers: { 'Content-Type': 'application/json' },
|
|
656
|
-
body: JSON.stringify({ agentId: 'agent_5a2b984c1', appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC' })
|
|
657
|
-
});
|
|
658
|
-
const { signedUrl } = await response.json();
|
|
659
|
-
|
|
660
435
|
const voiceSDK = new VoiceSDK_v2({
|
|
661
|
-
signedUrl: signedUrl, // Use signedUrl from backend
|
|
662
436
|
agentId: 'agent_5a2b984c1',
|
|
663
437
|
appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC',
|
|
664
438
|
|
|
@@ -759,16 +533,7 @@ await voiceSDK.connect();</code></pre>
|
|
|
759
533
|
<h3>Example 1: JavaScript/TypeScript with SDK v2</h3>
|
|
760
534
|
<pre><code>import { VoiceSDK_v2 } from 'ttp-agent-sdk';
|
|
761
535
|
|
|
762
|
-
// Get signed URL from your backend first
|
|
763
|
-
const response = await fetch('/api/get-voice-session', {
|
|
764
|
-
method: 'POST',
|
|
765
|
-
headers: { 'Content-Type': 'application/json' },
|
|
766
|
-
body: JSON.stringify({ agentId: 'agent_5a2b984c1', appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC' })
|
|
767
|
-
});
|
|
768
|
-
const { signedUrl } = await response.json();
|
|
769
|
-
|
|
770
536
|
const voiceSDK = new VoiceSDK_v2({
|
|
771
|
-
signedUrl: signedUrl, // Use signedUrl from backend
|
|
772
537
|
agentId: 'agent_5a2b984c1',
|
|
773
538
|
appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC',
|
|
774
539
|
|
|
@@ -1189,9 +954,8 @@ voiceSDK.on('domainError', (error) => {
|
|
|
1189
954
|
|
|
1190
955
|
<h2>Example: High-Quality Audio</h2>
|
|
1191
956
|
<pre><code>const voiceSDK = new VoiceSDK({
|
|
1192
|
-
signedUrl: signedUrl, // signedUrl from backend
|
|
1193
|
-
appId: 'your_app_id',
|
|
1194
957
|
agentId: 'agent_123',
|
|
958
|
+
appId: 'your_app_id',
|
|
1195
959
|
|
|
1196
960
|
// Request high-quality audio
|
|
1197
961
|
outputContainer: 'raw', // Raw PCM for lower latency
|
|
@@ -1211,9 +975,8 @@ voiceSDK.on('formatNegotiated', (format) => {
|
|
|
1211
975
|
|
|
1212
976
|
<h2>Example: Bandwidth-Optimized Audio</h2>
|
|
1213
977
|
<pre><code>const voiceSDK = new VoiceSDK({
|
|
1214
|
-
signedUrl: signedUrl, // signedUrl from backend
|
|
1215
|
-
appId: 'your_app_id',
|
|
1216
978
|
agentId: 'agent_123',
|
|
979
|
+
appId: 'your_app_id',
|
|
1217
980
|
|
|
1218
981
|
// Request compressed, low-bandwidth audio
|
|
1219
982
|
outputContainer: 'raw',
|
|
@@ -1293,10 +1056,7 @@ voiceSDK.on('formatNegotiated', (format) => {
|
|
|
1293
1056
|
agentId: 'agent_123', // Your AI agent ID
|
|
1294
1057
|
appId: 'your_app_id', // Your application ID
|
|
1295
1058
|
|
|
1296
|
-
// Optional -
|
|
1297
|
-
signedUrl: 'wss://speech.talktopc.com/ws/conv?signed_token=...', // Signed URL from your backend
|
|
1298
|
-
|
|
1299
|
-
// Optional - Agent Settings Override (requires signed URL with allowOverride=true)
|
|
1059
|
+
// Optional - Agent Settings Override (available when domain whitelist is configured)
|
|
1300
1060
|
agentSettingsOverride: {
|
|
1301
1061
|
prompt: "You are a helpful customer service assistant.",
|
|
1302
1062
|
temperature: 0.8,
|
|
@@ -1321,105 +1081,30 @@ voiceSDK.on('formatNegotiated', (format) => {
|
|
|
1321
1081
|
}
|
|
1322
1082
|
});</code></pre>
|
|
1323
1083
|
|
|
1324
|
-
<h2>
|
|
1325
|
-
<div class="
|
|
1326
|
-
<strong
|
|
1084
|
+
<h2>Access Control</h2>
|
|
1085
|
+
<div class="info-box">
|
|
1086
|
+
<strong>💡 Domain Whitelist:</strong> For production applications, configure a domain whitelist in your agent's admin panel to control which websites can connect to your agent.
|
|
1327
1087
|
</div>
|
|
1328
1088
|
|
|
1329
|
-
<p>
|
|
1089
|
+
<p>The widget connects directly using <code>agentId</code> and <code>appId</code>. No backend authentication step is needed:</p>
|
|
1330
1090
|
|
|
1331
|
-
<pre><code
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
'Content-Type': 'application/json',
|
|
1338
|
-
'Authorization': `Bearer ${getAuthToken()}` // Your auth token
|
|
1339
|
-
},
|
|
1340
|
-
body: JSON.stringify({
|
|
1341
|
-
agentId: 'agent_123',
|
|
1342
|
-
appId: 'your_app_id',
|
|
1343
|
-
variables: {
|
|
1344
|
-
userName: 'John Doe',
|
|
1345
|
-
page: 'homepage'
|
|
1346
|
-
}
|
|
1347
|
-
})
|
|
1348
|
-
});
|
|
1349
|
-
|
|
1350
|
-
if (!response.ok) {
|
|
1351
|
-
throw new Error(`Backend API error: ${response.status}`);
|
|
1352
|
-
}
|
|
1353
|
-
|
|
1354
|
-
const data = await response.json();
|
|
1355
|
-
|
|
1356
|
-
// Backend must return signedUrl field
|
|
1357
|
-
if (!data.signedUrl) {
|
|
1358
|
-
throw new Error('Backend response must contain "signedUrl" field');
|
|
1091
|
+
<pre><code>const widget = new TTPAgentSDK.TTPChatWidget({
|
|
1092
|
+
agentId: 'agent_123',
|
|
1093
|
+
appId: 'your_app_id',
|
|
1094
|
+
variables: {
|
|
1095
|
+
userName: 'John Doe',
|
|
1096
|
+
page: 'homepage'
|
|
1359
1097
|
}
|
|
1360
|
-
|
|
1361
|
-
// Step 2: Initialize widget with signedUrl
|
|
1362
|
-
const widget = new TTPAgentSDK.TTPChatWidget({
|
|
1363
|
-
agentId: 'agent_123',
|
|
1364
|
-
appId: 'your_app_id',
|
|
1365
|
-
signedUrl: data.signedUrl, // Use signed URL from backend
|
|
1366
|
-
variables: {
|
|
1367
|
-
userName: 'John Doe',
|
|
1368
|
-
page: 'homepage'
|
|
1369
|
-
}
|
|
1370
|
-
});
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
// Initialize when ready
|
|
1374
|
-
initializeWidget();</code></pre>
|
|
1098
|
+
});</code></pre>
|
|
1375
1099
|
|
|
1376
1100
|
<div class="info-box">
|
|
1377
1101
|
<strong>📋 Important:</strong>
|
|
1378
1102
|
<ul style="margin-top: 10px; margin-left: 20px;">
|
|
1379
|
-
<li>The widget
|
|
1380
|
-
<li>
|
|
1381
|
-
<li>
|
|
1382
|
-
<li>If <code>signedUrl</code> is not provided, the widget will construct a URL from <code>agentId</code> and <code>appId</code> (less secure)</li>
|
|
1383
|
-
<li>Your backend should authenticate with TTP backend using your API key (see <a href="#authentication">Authentication</a> section)</li>
|
|
1103
|
+
<li>The widget only needs <code>agentId</code> and <code>appId</code> to connect</li>
|
|
1104
|
+
<li>Access control is managed via domain whitelist in the admin panel</li>
|
|
1105
|
+
<li>Optionally pass <code>websocketUrl</code> to override the default WebSocket endpoint</li>
|
|
1384
1106
|
</ul>
|
|
1385
1107
|
</div>
|
|
1386
|
-
|
|
1387
|
-
<h3>Backend Implementation Example</h3>
|
|
1388
|
-
<p>Your backend endpoint should request signed URLs from TTP:</p>
|
|
1389
|
-
<pre><code>// Your Backend (Node.js/Express example)
|
|
1390
|
-
app.post('/api/get-voice-session', async (req, res) => {
|
|
1391
|
-
const { agentId, appId, variables } = req.body;
|
|
1392
|
-
|
|
1393
|
-
// Authenticate your user
|
|
1394
|
-
if (!req.user) {
|
|
1395
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
// Backend-to-Backend: Request signed URL from TTP
|
|
1399
|
-
const response = await fetch('https://backend.talktopc.com/api/public/agents/signed-url', {
|
|
1400
|
-
method: 'POST',
|
|
1401
|
-
headers: {
|
|
1402
|
-
'Content-Type': 'application/json',
|
|
1403
|
-
'Authorization': `Bearer ${process.env.TTP_API_KEY}` // Your TTP API key
|
|
1404
|
-
},
|
|
1405
|
-
body: JSON.stringify({
|
|
1406
|
-
agentId,
|
|
1407
|
-
appId,
|
|
1408
|
-
variables
|
|
1409
|
-
})
|
|
1410
|
-
});
|
|
1411
|
-
|
|
1412
|
-
if (!response.ok) {
|
|
1413
|
-
return res.status(500).json({ error: 'Failed to get signed URL' });
|
|
1414
|
-
}
|
|
1415
|
-
|
|
1416
|
-
const data = await response.json();
|
|
1417
|
-
|
|
1418
|
-
// Return signedUrl to frontend
|
|
1419
|
-
res.json({
|
|
1420
|
-
signedUrl: data.signedUrl
|
|
1421
|
-
});
|
|
1422
|
-
});</code></pre>
|
|
1423
1108
|
|
|
1424
1109
|
<h2>Advanced Customization</h2>
|
|
1425
1110
|
|
|
@@ -1466,13 +1151,12 @@ app.post('/api/get-voice-session', async (req, res) => {
|
|
|
1466
1151
|
|
|
1467
1152
|
<h3>Agent Settings Override</h3>
|
|
1468
1153
|
<div class="info-box">
|
|
1469
|
-
<strong
|
|
1154
|
+
<strong>💡 Access Control:</strong> Agent settings override is available when the agent has domain whitelist configured in the admin panel.
|
|
1470
1155
|
</div>
|
|
1471
1156
|
<p>Dynamically customize agent behavior, voice, and personality on a per-session basis:</p>
|
|
1472
1157
|
<pre><code>const widget = new TTPAgentSDK.TTPChatWidget({
|
|
1473
1158
|
agentId: 'agent_123',
|
|
1474
1159
|
appId: 'your_app_id',
|
|
1475
|
-
signedUrl: 'wss://speech.talktopc.com/ws/conv?signed_token=...', // Required: signed URL with allowOverride=true
|
|
1476
1160
|
|
|
1477
1161
|
// Override agent settings dynamically
|
|
1478
1162
|
agentSettingsOverride: {
|
|
@@ -1696,16 +1380,16 @@ document.getElementById('myButton').onclick = () => {
|
|
|
1696
1380
|
<td>Custom variables to pass to agent</td>
|
|
1697
1381
|
</tr>
|
|
1698
1382
|
<tr>
|
|
1699
|
-
<td><code>
|
|
1700
|
-
<td>string
|
|
1383
|
+
<td><code>websocketUrl</code></td>
|
|
1384
|
+
<td>string</td>
|
|
1701
1385
|
<td>null</td>
|
|
1702
|
-
<td>
|
|
1386
|
+
<td>Optional custom WebSocket base URL (defaults to wss://speech.talktopc.com/ws/conv)</td>
|
|
1703
1387
|
</tr>
|
|
1704
1388
|
<tr>
|
|
1705
1389
|
<td><code>agentSettingsOverride</code></td>
|
|
1706
1390
|
<td>object</td>
|
|
1707
1391
|
<td>null</td>
|
|
1708
|
-
<td>Override agent settings dynamically
|
|
1392
|
+
<td>Override agent settings dynamically. See <a href="#agent-override">Agent Settings Override</a> for details.</td>
|
|
1709
1393
|
</tr>
|
|
1710
1394
|
<tr>
|
|
1711
1395
|
<td><code>customStyles</code></td>
|
|
@@ -1713,10 +1397,98 @@ document.getElementById('myButton').onclick = () => {
|
|
|
1713
1397
|
<td>''</td>
|
|
1714
1398
|
<td>Custom CSS to inject</td>
|
|
1715
1399
|
</tr>
|
|
1400
|
+
<tr>
|
|
1401
|
+
<td><code>useShadowDOM</code></td>
|
|
1402
|
+
<td>boolean</td>
|
|
1403
|
+
<td>true</td>
|
|
1404
|
+
<td>Enable Shadow DOM for CSS isolation. Set to <code>false</code> for Shopify compatibility. See <a href="#shadow-dom-config">Shadow DOM Configuration</a> below.</td>
|
|
1405
|
+
</tr>
|
|
1716
1406
|
</tbody>
|
|
1717
1407
|
</table>
|
|
1718
1408
|
</details>
|
|
1719
1409
|
|
|
1410
|
+
<div id="shadow-dom-config" class="info-box" style="margin: 20px 0; padding: 20px; background: #f8f9fa; border-left: 4px solid #7C3AED;">
|
|
1411
|
+
<h3 style="margin-top: 0;">Shadow DOM Configuration (<code>useShadowDOM</code>)</h3>
|
|
1412
|
+
|
|
1413
|
+
<p><strong>What is Shadow DOM?</strong></p>
|
|
1414
|
+
<p>Shadow DOM is a web standard that provides CSS isolation by creating a separate DOM tree that doesn't inherit styles from the parent page. This prevents theme CSS from interfering with the widget's appearance.</p>
|
|
1415
|
+
|
|
1416
|
+
<p><strong>When to Use Shadow DOM:</strong></p>
|
|
1417
|
+
<ul style="margin: 10px 0 10px 20px;">
|
|
1418
|
+
<li><strong>✅ WordPress:</strong> Use Shadow DOM (<code>useShadowDOM: true</code> or omit - defaults to <code>true</code>)</li>
|
|
1419
|
+
<li><strong>✅ Most platforms:</strong> Shadow DOM works well on most websites and platforms</li>
|
|
1420
|
+
<li><strong>❌ Shopify:</strong> Disable Shadow DOM (<code>useShadowDOM: false</code>) due to rendering issues</li>
|
|
1421
|
+
</ul>
|
|
1422
|
+
|
|
1423
|
+
<p><strong>Why We Need This Option:</strong></p>
|
|
1424
|
+
<p>While Shadow DOM provides excellent CSS isolation, some platforms (notably Shopify) have rendering issues where Shadow DOM elements render with 0x0 dimensions, making the widget invisible. By setting <code>useShadowDOM: false</code>, the widget uses regular DOM with targeted CSS resets instead, ensuring visibility while still protecting against most theme conflicts.</p>
|
|
1425
|
+
|
|
1426
|
+
<p><strong>Platform-Specific Recommendations:</strong></p>
|
|
1427
|
+
<table class="properties-table" style="margin: 15px 0;">
|
|
1428
|
+
<thead>
|
|
1429
|
+
<tr>
|
|
1430
|
+
<th>Platform</th>
|
|
1431
|
+
<th>Recommended Setting</th>
|
|
1432
|
+
<th>Reason</th>
|
|
1433
|
+
</tr>
|
|
1434
|
+
</thead>
|
|
1435
|
+
<tbody>
|
|
1436
|
+
<tr>
|
|
1437
|
+
<td><strong>WordPress</strong></td>
|
|
1438
|
+
<td><code>useShadowDOM: true</code> (default)</td>
|
|
1439
|
+
<td>Shadow DOM works perfectly and provides better CSS isolation</td>
|
|
1440
|
+
</tr>
|
|
1441
|
+
<tr>
|
|
1442
|
+
<td><strong>Shopify</strong></td>
|
|
1443
|
+
<td><code>useShadowDOM: false</code></td>
|
|
1444
|
+
<td>Shadow DOM elements render with 0x0 dimensions, making widget invisible</td>
|
|
1445
|
+
</tr>
|
|
1446
|
+
<tr>
|
|
1447
|
+
<td><strong>Wix</strong></td>
|
|
1448
|
+
<td><code>useShadowDOM: true</code> (default)</td>
|
|
1449
|
+
<td>Shadow DOM works well on Wix</td>
|
|
1450
|
+
</tr>
|
|
1451
|
+
<tr>
|
|
1452
|
+
<td><strong>Custom Websites</strong></td>
|
|
1453
|
+
<td><code>useShadowDOM: true</code> (default)</td>
|
|
1454
|
+
<td>Use Shadow DOM unless you experience rendering issues</td>
|
|
1455
|
+
</tr>
|
|
1456
|
+
</tbody>
|
|
1457
|
+
</table>
|
|
1458
|
+
|
|
1459
|
+
<p><strong>Example Usage:</strong></p>
|
|
1460
|
+
<pre><code class="language-javascript">// WordPress (default - Shadow DOM enabled)
|
|
1461
|
+
const widget = new TTPChatWidget({
|
|
1462
|
+
agentId: 'your-agent-id',
|
|
1463
|
+
// useShadowDOM defaults to true, so widget is isolated from theme CSS
|
|
1464
|
+
});
|
|
1465
|
+
|
|
1466
|
+
// Shopify (disable Shadow DOM)
|
|
1467
|
+
const widget = new TTPChatWidget({
|
|
1468
|
+
agentId: 'your-agent-id',
|
|
1469
|
+
useShadowDOM: false // Required for Shopify compatibility
|
|
1470
|
+
});
|
|
1471
|
+
|
|
1472
|
+
// If widget is invisible, try disabling Shadow DOM
|
|
1473
|
+
const widget = new TTPChatWidget({
|
|
1474
|
+
agentId: 'your-agent-id',
|
|
1475
|
+
useShadowDOM: false // Fallback if Shadow DOM causes rendering issues
|
|
1476
|
+
});</code></pre>
|
|
1477
|
+
|
|
1478
|
+
<p><strong>How It Works:</strong></p>
|
|
1479
|
+
<ul style="margin: 10px 0 10px 20px;">
|
|
1480
|
+
<li><strong>With Shadow DOM (<code>useShadowDOM: true</code>):</strong> Widget is rendered inside a Shadow DOM tree, completely isolated from page CSS. Styles are injected into the shadow root.</li>
|
|
1481
|
+
<li><strong>Without Shadow DOM (<code>useShadowDOM: false</code>):</strong> Widget is rendered in regular DOM. Styles are injected into the document <code><head></code> with high-specificity selectors to prevent theme CSS conflicts. Targeted CSS resets protect against common theme issues while preserving widget functionality.</li>
|
|
1482
|
+
</ul>
|
|
1483
|
+
|
|
1484
|
+
<p><strong>⚠️ Important Notes:</strong></p>
|
|
1485
|
+
<ul style="margin: 10px 0 10px 20px;">
|
|
1486
|
+
<li>When <code>useShadowDOM: false</code>, the widget uses targeted CSS resets instead of aggressive resets to preserve internal widget styles</li>
|
|
1487
|
+
<li>If you experience layout issues with <code>useShadowDOM: false</code>, check if your theme's CSS is overriding widget styles - you may need to add more specific CSS rules</li>
|
|
1488
|
+
<li>The widget automatically handles CSS injection differently based on this setting - no additional configuration needed</li>
|
|
1489
|
+
</ul>
|
|
1490
|
+
</div>
|
|
1491
|
+
|
|
1720
1492
|
<details>
|
|
1721
1493
|
<summary><strong>Positioning</strong></summary>
|
|
1722
1494
|
<table class="properties-table">
|
|
@@ -2099,6 +1871,24 @@ document.getElementById('myButton').onclick = () => {
|
|
|
2099
1871
|
<td>'#64748b'</td>
|
|
2100
1872
|
<td>Status subtitle text color</td>
|
|
2101
1873
|
</tr>
|
|
1874
|
+
<tr>
|
|
1875
|
+
<td><code>voice.startCallTitle</code></td>
|
|
1876
|
+
<td>string</td>
|
|
1877
|
+
<td>null</td>
|
|
1878
|
+
<td>Custom text for "Click to Start Call" title (bypasses translations)</td>
|
|
1879
|
+
</tr>
|
|
1880
|
+
<tr>
|
|
1881
|
+
<td><code>voice.startCallSubtitle</code></td>
|
|
1882
|
+
<td>string</td>
|
|
1883
|
+
<td>null</td>
|
|
1884
|
+
<td>Custom text for "Real-time voice conversation" subtitle (bypasses translations)</td>
|
|
1885
|
+
</tr>
|
|
1886
|
+
<tr>
|
|
1887
|
+
<td><code>voice.startCallButtonText</code></td>
|
|
1888
|
+
<td>string</td>
|
|
1889
|
+
<td>null</td>
|
|
1890
|
+
<td>Custom text for "Start Call" button (bypasses translations)</td>
|
|
1891
|
+
</tr>
|
|
2102
1892
|
<tr>
|
|
2103
1893
|
<td><code>voice.startCallButtonColor</code></td>
|
|
2104
1894
|
<td>string</td>
|
|
@@ -2392,10 +2182,10 @@ document.getElementById('myButton').onclick = () => {
|
|
|
2392
2182
|
</thead>
|
|
2393
2183
|
<tbody>
|
|
2394
2184
|
<tr>
|
|
2395
|
-
<td><code>
|
|
2185
|
+
<td><code>websocketUrl</code></td>
|
|
2396
2186
|
<td>string</td>
|
|
2397
2187
|
<td>Optional</td>
|
|
2398
|
-
<td>
|
|
2188
|
+
<td>Custom WebSocket base URL (defaults to wss://speech.talktopc.com/ws/conv). If not provided, URL is constructed from agentId/appId.</td>
|
|
2399
2189
|
</tr>
|
|
2400
2190
|
<tr>
|
|
2401
2191
|
<td><code>demo</code></td>
|
|
@@ -2519,14 +2309,9 @@ class VoiceAssistant {
|
|
|
2519
2309
|
}
|
|
2520
2310
|
|
|
2521
2311
|
async initialize(agentId, overrides = {}) {
|
|
2522
|
-
// Step 1: Get signed URL
|
|
2523
|
-
const signedUrl = await this.getSignedUrl(agentId);
|
|
2524
|
-
|
|
2525
|
-
// Step 2: Create SDK
|
|
2526
2312
|
this.sdk = new VoiceSDK({
|
|
2527
|
-
signedUrl: signedUrl, // signedUrl from backend
|
|
2528
|
-
appId: 'your_app_id',
|
|
2529
2313
|
agentId: agentId,
|
|
2314
|
+
appId: 'your_app_id',
|
|
2530
2315
|
agentSettingsOverride: overrides
|
|
2531
2316
|
});
|
|
2532
2317
|
|
|
@@ -2570,21 +2355,6 @@ class VoiceAssistant {
|
|
|
2570
2355
|
});
|
|
2571
2356
|
}
|
|
2572
2357
|
|
|
2573
|
-
async getSignedUrl(agentId) {
|
|
2574
|
-
const response = await fetch('/api/get-voice-session', {
|
|
2575
|
-
method: 'POST',
|
|
2576
|
-
headers: {
|
|
2577
|
-
'Content-Type': 'application/json'
|
|
2578
|
-
},
|
|
2579
|
-
body: JSON.stringify({
|
|
2580
|
-
agentId: agentId
|
|
2581
|
-
})
|
|
2582
|
-
});
|
|
2583
|
-
|
|
2584
|
-
const { signedUrl } = await response.json();
|
|
2585
|
-
return signedUrl;
|
|
2586
|
-
}
|
|
2587
|
-
|
|
2588
2358
|
async toggleRecording() {
|
|
2589
2359
|
if (!this.isConnected) return;
|
|
2590
2360
|
|
|
@@ -2642,24 +2412,9 @@ function VoiceChat() {
|
|
|
2642
2412
|
// Initialize SDK
|
|
2643
2413
|
useEffect(() => {
|
|
2644
2414
|
async function initSDK() {
|
|
2645
|
-
// Get signed URL
|
|
2646
|
-
const response = await fetch('/api/get-voice-session', {
|
|
2647
|
-
method: 'POST',
|
|
2648
|
-
headers: {
|
|
2649
|
-
'Content-Type': 'application/json'
|
|
2650
|
-
},
|
|
2651
|
-
body: JSON.stringify({
|
|
2652
|
-
agentId: 'agent_123'
|
|
2653
|
-
})
|
|
2654
|
-
});
|
|
2655
|
-
|
|
2656
|
-
const { signedUrl } = await response.json();
|
|
2657
|
-
|
|
2658
|
-
// Create SDK
|
|
2659
2415
|
const sdk = new VoiceSDK({
|
|
2660
|
-
signedUrl: signedUrl, // signedUrl from backend
|
|
2661
|
-
appId: 'your_app_id',
|
|
2662
2416
|
agentId: 'agent_123',
|
|
2417
|
+
appId: 'your_app_id',
|
|
2663
2418
|
agentSettingsOverride: {
|
|
2664
2419
|
language: 'es',
|
|
2665
2420
|
temperature: 0.9
|
|
@@ -2730,38 +2485,14 @@ export default VoiceChat;</code></pre>
|
|
|
2730
2485
|
<pre><code>import { VoiceButton } from 'ttp-agent-sdk/react';</code></pre>
|
|
2731
2486
|
|
|
2732
2487
|
<h2>Basic Usage</h2>
|
|
2733
|
-
<pre><code>import React
|
|
2488
|
+
<pre><code>import React from 'react';
|
|
2734
2489
|
import { VoiceButton } from 'ttp-agent-sdk/react';
|
|
2735
2490
|
|
|
2736
2491
|
function App() {
|
|
2737
|
-
const [signedUrl, setSignedUrl] = useState(null);
|
|
2738
|
-
|
|
2739
|
-
useEffect(() => {
|
|
2740
|
-
async function fetchSignedUrl() {
|
|
2741
|
-
const response = await fetch('/api/get-voice-session', {
|
|
2742
|
-
method: 'POST',
|
|
2743
|
-
headers: {
|
|
2744
|
-
'Content-Type': 'application/json'
|
|
2745
|
-
},
|
|
2746
|
-
body: JSON.stringify({
|
|
2747
|
-
agentId: 'agent_123'
|
|
2748
|
-
})
|
|
2749
|
-
});
|
|
2750
|
-
|
|
2751
|
-
const { signedUrl } = await response.json();
|
|
2752
|
-
setSignedUrl(signedUrl);
|
|
2753
|
-
}
|
|
2754
|
-
|
|
2755
|
-
fetchSignedUrl();
|
|
2756
|
-
}, []);
|
|
2757
|
-
|
|
2758
|
-
if (!signedUrl) return <div>Loading...</div>;
|
|
2759
|
-
|
|
2760
2492
|
return (
|
|
2761
2493
|
<VoiceButton
|
|
2762
|
-
signedUrl={signedUrl} {/* signedUrl from backend */}
|
|
2763
|
-
appId="your_app_id"
|
|
2764
2494
|
agentId="agent_123"
|
|
2495
|
+
appId="your_app_id"
|
|
2765
2496
|
agentSettingsOverride={{
|
|
2766
2497
|
language: 'es',
|
|
2767
2498
|
temperature: 0.9
|
|
@@ -2785,10 +2516,10 @@ function App() {
|
|
|
2785
2516
|
</thead>
|
|
2786
2517
|
<tbody>
|
|
2787
2518
|
<tr>
|
|
2788
|
-
<td><code>
|
|
2519
|
+
<td><code>agentId</code></td>
|
|
2789
2520
|
<td>string</td>
|
|
2790
2521
|
<td>Yes</td>
|
|
2791
|
-
<td>
|
|
2522
|
+
<td>The AI agent identifier</td>
|
|
2792
2523
|
</tr>
|
|
2793
2524
|
<tr>
|
|
2794
2525
|
<td><code>appId</code></td>
|
|
@@ -2797,10 +2528,10 @@ function App() {
|
|
|
2797
2528
|
<td>Your application ID</td>
|
|
2798
2529
|
</tr>
|
|
2799
2530
|
<tr>
|
|
2800
|
-
<td><code>
|
|
2531
|
+
<td><code>websocketUrl</code></td>
|
|
2801
2532
|
<td>string</td>
|
|
2802
|
-
<td>
|
|
2803
|
-
<td>
|
|
2533
|
+
<td>No</td>
|
|
2534
|
+
<td>Optional custom WebSocket base URL (defaults to wss://speech.talktopc.com/ws/conv)</td>
|
|
2804
2535
|
</tr>
|
|
2805
2536
|
<tr>
|
|
2806
2537
|
<td><code>agentSettingsOverride</code></td>
|
|
@@ -2931,10 +2662,10 @@ function App() {
|
|
|
2931
2662
|
</thead>
|
|
2932
2663
|
<tbody>
|
|
2933
2664
|
<tr>
|
|
2934
|
-
<td><code>
|
|
2665
|
+
<td><code>agentId</code></td>
|
|
2935
2666
|
<td>string</td>
|
|
2936
2667
|
<td>Yes</td>
|
|
2937
|
-
<td>
|
|
2668
|
+
<td>The AI agent identifier to connect to</td>
|
|
2938
2669
|
</tr>
|
|
2939
2670
|
<tr>
|
|
2940
2671
|
<td><code>appId</code></td>
|
|
@@ -2943,10 +2674,10 @@ function App() {
|
|
|
2943
2674
|
<td>Your application identifier</td>
|
|
2944
2675
|
</tr>
|
|
2945
2676
|
<tr>
|
|
2946
|
-
<td><code>
|
|
2677
|
+
<td><code>websocketUrl</code></td>
|
|
2947
2678
|
<td>string</td>
|
|
2948
|
-
<td>
|
|
2949
|
-
<td>
|
|
2679
|
+
<td>No</td>
|
|
2680
|
+
<td>Optional custom WebSocket base URL (defaults to wss://speech.talktopc.com/ws/conv)</td>
|
|
2950
2681
|
</tr>
|
|
2951
2682
|
<tr>
|
|
2952
2683
|
<td><code>agentSettingsOverride</code></td>
|
|
@@ -3053,9 +2784,8 @@ function App() {
|
|
|
3053
2784
|
|
|
3054
2785
|
<h4>Example: Custom Audio Format</h4>
|
|
3055
2786
|
<pre><code>const voiceSDK = new VoiceSDK({
|
|
3056
|
-
signedUrl: signedUrl, // signedUrl from backend
|
|
3057
|
-
appId: 'your_app_id',
|
|
3058
2787
|
agentId: 'agent_123',
|
|
2788
|
+
appId: 'your_app_id',
|
|
3059
2789
|
|
|
3060
2790
|
// Input format (what we send to server)
|
|
3061
2791
|
sampleRate: 16000,
|