ttp-agent-sdk 2.5.6 → 2.5.7

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/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.3.19</p>
26
+ <p class="version" style="margin: 0;">v2.3.18</p>
27
27
  </div>
28
28
  </div>
29
29
  </div>
@@ -43,6 +43,7 @@
43
43
  <ul>
44
44
  <li><a href="#authentication" class="nav-link">Authentication</a></li>
45
45
  <li><a href="#agent-override" class="nav-link">Agent Override</a></li>
46
+ <li><a href="#variables" class="nav-link">Variables in Hello Request</a></li>
46
47
  <li><a href="#events" class="nav-link">Events & Callbacks</a></li>
47
48
  <li><a href="#protocol-v2" class="nav-link">Protocol v2 - Format Negotiation</a></li>
48
49
  </ul>
@@ -133,19 +134,19 @@
133
134
  <span class="quick-link-arrow">→</span>
134
135
  </a>
135
136
 
136
- <a href="#java-sdk" class="quick-link-card">
137
- <div class="quick-link-icon">☕</div>
138
- <h3>Java SDK</h3>
139
- <p>Backend SDK for server-side TTS</p>
140
- <span class="quick-link-arrow">→</span>
141
- </a>
142
-
143
137
  <a href="#text-to-speech" class="quick-link-card">
144
138
  <div class="quick-link-icon">🔊</div>
145
139
  <h3>Text To Speech</h3>
146
140
  <p>REST API for voice synthesis</p>
147
141
  <span class="quick-link-arrow">→</span>
148
142
  </a>
143
+
144
+ <a href="#java-sdk" class="quick-link-card">
145
+ <div class="quick-link-icon">☕</div>
146
+ <h3>Java SDK</h3>
147
+ <p>Backend SDK for server-side TTS</p>
148
+ <span class="quick-link-arrow">→</span>
149
+ </a>
149
150
  </div>
150
151
  </div>
151
152
 
@@ -256,7 +257,7 @@ const { signedUrl } = await response.json();</code></pre>
256
257
  <pre><code>import { VoiceSDK } from 'ttp-agent-sdk';
257
258
 
258
259
  const voiceSDK = new VoiceSDK({
259
- websocketUrl: signedUrl, // Signed URL from step 1
260
+ signedUrl: signedUrl, // signedUrl from step 1
260
261
  appId: 'your_app_id', // Your application ID
261
262
  agentId: 'agent_123', // The AI agent to connect to
262
263
 
@@ -563,7 +564,7 @@ app.post('/api/get-voice-session', async (req, res) => {
563
564
 
564
565
  <h2>Example</h2>
565
566
  <pre><code>const voiceSDK = new VoiceSDK({
566
- websocketUrl: signedUrl, // Signed URL from your backend
567
+ signedUrl: signedUrl, // signedUrl from your backend
567
568
  appId: 'your_app_id', // Your application ID
568
569
  agentId: 'agent_123', // The AI agent to connect to
569
570
 
@@ -635,6 +636,371 @@ app.post('/api/get-voice-session', async (req, res) => {
635
636
  </div>
636
637
  </section>
637
638
 
639
+ <!-- Variables in Hello Request -->
640
+ <section id="variables" class="doc-section">
641
+ <h1>Variables in Hello Request</h1>
642
+
643
+ <h2>Overview</h2>
644
+ <p>Variables allow you to pass dynamic values to your agent that will be used to replace placeholders in the system prompt and first message. Variables sent in the hello request take precedence over default variables stored in the agent configuration.</p>
645
+
646
+ <h2>Hello Message Format</h2>
647
+
648
+ <h3>SDK v2 Format (Recommended)</h3>
649
+ <p>When using VoiceSDK v2, variables are passed in the SDK constructor:</p>
650
+ <pre><code>import { VoiceSDK_v2 } from 'ttp-agent-sdk';
651
+
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
+ const voiceSDK = new VoiceSDK_v2({
661
+ signedUrl: signedUrl, // Use signedUrl from backend
662
+ agentId: 'agent_5a2b984c1',
663
+ appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC',
664
+
665
+ // Variables (optional)
666
+ variables: {
667
+ USER_NAME: 'John',
668
+ ACCOUNT_TYPE: 'premium',
669
+ LANGUAGE: 'en-US'
670
+ },
671
+
672
+ // Audio format configuration
673
+ sampleRate: 44100,
674
+ channels: 1,
675
+ bitDepth: 16,
676
+ outputContainer: 'raw',
677
+ outputEncoding: 'pcm',
678
+ outputSampleRate: 44100,
679
+ outputChannels: 1,
680
+ outputBitDepth: 16,
681
+ outputFrameDurationMs: 600
682
+ });
683
+
684
+ await voiceSDK.connect();</code></pre>
685
+
686
+ <h3>Raw WebSocket Format</h3>
687
+ <p>If connecting via raw WebSocket (without SDK), send variables in the hello message:</p>
688
+ <pre><code>{
689
+ "t": "hello",
690
+ "v": 2,
691
+ "variables": {
692
+ "USER_NAME": "John",
693
+ "ACCOUNT_TYPE": "premium",
694
+ "LANGUAGE": "en-US"
695
+ },
696
+ "inputFormat": {
697
+ "encoding": "pcm",
698
+ "sampleRate": 44100,
699
+ "channels": 1,
700
+ "bitDepth": 16
701
+ },
702
+ "requestedOutputFormat": {
703
+ "encoding": "pcm",
704
+ "sampleRate": 44100,
705
+ "channels": 1,
706
+ "bitDepth": 16,
707
+ "container": "raw"
708
+ },
709
+ "outputFrameDurationMs": 600
710
+ }</code></pre>
711
+
712
+ <h2>Variable Format</h2>
713
+ <p>Variables are sent as a JSON object where:</p>
714
+ <ul>
715
+ <li><strong>Keys</strong>: Variable names (case-sensitive, e.g., <code>USER_NAME</code>)</li>
716
+ <li><strong>Values</strong>: String values that will replace <code>{{VARIABLE_NAME}}</code> in the prompt</li>
717
+ </ul>
718
+
719
+ <h3>Example</h3>
720
+ <pre><code>{
721
+ "variables": {
722
+ "USER_NAME": "John",
723
+ "ACCOUNT_TYPE": "premium",
724
+ "LANGUAGE": "en-US",
725
+ "COMPANY": "Acme Corp"
726
+ }
727
+ }</code></pre>
728
+
729
+ <h2>Variable Replacement Priority</h2>
730
+ <p>Variables are replaced in the following priority order:</p>
731
+ <ol>
732
+ <li><strong>Hello Variables</strong> (highest priority) - Variables sent in the hello request</li>
733
+ <li><strong>Default Variables</strong> - Variables stored in agent configuration (Redis)</li>
734
+ <li><strong>Leave as-is</strong> - If no value found, <code>{{VARIABLE_NAME}}</code> remains unchanged</li>
735
+ </ol>
736
+
737
+ <h3>Example Priority</h3>
738
+ <p><strong>Agent Configuration (Redis):</strong></p>
739
+ <pre><code>{
740
+ "USER_NAME": "David",
741
+ "ACCOUNT_TYPE": "premium"
742
+ }</code></pre>
743
+
744
+ <p><strong>Hello Request:</strong></p>
745
+ <pre><code>{
746
+ "variables": {
747
+ "USER_NAME": "John"
748
+ }
749
+ }</code></pre>
750
+
751
+ <p><strong>Result:</strong></p>
752
+ <ul>
753
+ <li><code>{{USER_NAME}}</code> → <code>"John"</code> (from hello - takes precedence)</li>
754
+ <li><code>{{ACCOUNT_TYPE}}</code> → <code>"premium"</code> (from defaults - hello doesn't override)</li>
755
+ </ul>
756
+
757
+ <h2>Usage Examples</h2>
758
+
759
+ <h3>Example 1: JavaScript/TypeScript with SDK v2</h3>
760
+ <pre><code>import { VoiceSDK_v2 } from 'ttp-agent-sdk';
761
+
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
+ const voiceSDK = new VoiceSDK_v2({
771
+ signedUrl: signedUrl, // Use signedUrl from backend
772
+ agentId: 'agent_5a2b984c1',
773
+ appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC',
774
+
775
+ variables: {
776
+ USER_NAME: 'John Doe',
777
+ ACCOUNT_TYPE: 'premium',
778
+ LANGUAGE: 'en-US'
779
+ },
780
+
781
+ // ... audio format config
782
+ });
783
+
784
+ await voiceSDK.connect();</code></pre>
785
+
786
+ <h3>Example 2: Raw WebSocket (JavaScript)</h3>
787
+ <pre><code>const ws = new WebSocket('wss://speech.talktopc.com/ws/conv?agentId=agent_5a2b984c1&appId=app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC');
788
+
789
+ ws.onopen = () => {
790
+ const helloMessage = {
791
+ t: 'hello',
792
+ v: 2,
793
+ variables: {
794
+ USER_NAME: 'John',
795
+ ACCOUNT_TYPE: 'premium',
796
+ LANGUAGE: 'en-US'
797
+ },
798
+ inputFormat: {
799
+ encoding: 'pcm',
800
+ sampleRate: 44100,
801
+ channels: 1,
802
+ bitDepth: 16
803
+ },
804
+ requestedOutputFormat: {
805
+ encoding: 'pcm',
806
+ sampleRate: 44100,
807
+ channels: 1,
808
+ bitDepth: 16,
809
+ container: 'raw'
810
+ },
811
+ outputFrameDurationMs: 600
812
+ };
813
+
814
+ ws.send(JSON.stringify(helloMessage));
815
+ };</code></pre>
816
+
817
+ <h3>Example 3: Python WebSocket</h3>
818
+ <pre><code>import websocket
819
+ import json
820
+
821
+ def on_open(ws):
822
+ hello_message = {
823
+ "t": "hello",
824
+ "v": 2,
825
+ "variables": {
826
+ "USER_NAME": "John",
827
+ "ACCOUNT_TYPE": "premium",
828
+ "LANGUAGE": "en-US"
829
+ },
830
+ "inputFormat": {
831
+ "encoding": "pcm",
832
+ "sampleRate": 44100,
833
+ "channels": 1,
834
+ "bitDepth": 16
835
+ },
836
+ "requestedOutputFormat": {
837
+ "encoding": "pcm",
838
+ "sampleRate": 44100,
839
+ "channels": 1,
840
+ "bitDepth": 16,
841
+ "container": "raw"
842
+ },
843
+ "outputFrameDurationMs": 600
844
+ }
845
+
846
+ ws.send(json.dumps(hello_message))
847
+
848
+ ws = websocket.WebSocketApp(
849
+ "wss://speech.talktopc.com/ws/conv?agentId=agent_5a2b984c1&appId=app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC",
850
+ on_open=on_open
851
+ )
852
+ ws.run_forever()</code></pre>
853
+
854
+ <h3>Example 4: cURL / wscat</h3>
855
+ <pre><code># Using wscat
856
+ wscat -c "wss://speech.talktopc.com/ws/conv?agentId=agent_5a2b984c1&appId=app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC"
857
+
858
+ # Then send:
859
+ {"t":"hello","v":2,"variables":{"USER_NAME":"John","ACCOUNT_TYPE":"premium"},"inputFormat":{"encoding":"pcm","sampleRate":44100,"channels":1,"bitDepth":16},"requestedOutputFormat":{"encoding":"pcm","sampleRate":44100,"channels":1,"bitDepth":16,"container":"raw"},"outputFrameDurationMs":600}</code></pre>
860
+
861
+ <h2>Agent Prompt Setup</h2>
862
+ <p>To use variables in your agent, include placeholders in the system prompt or first message:</p>
863
+
864
+ <h3>System Prompt Example</h3>
865
+ <pre><code>Your name is {{AGENT_NAME}}.
866
+ You are helping {{USER_NAME}} who has a {{ACCOUNT_TYPE}} account.
867
+ Speak in {{LANGUAGE}}.</code></pre>
868
+
869
+ <h3>First Message Example</h3>
870
+ <pre><code>Hello {{USER_NAME}}! Welcome to our {{ACCOUNT_TYPE}} service.</code></pre>
871
+
872
+ <h2>Backend Processing</h2>
873
+ <p>When the hello request is received with variables:</p>
874
+ <ol>
875
+ <li><strong>Variables are extracted</strong> from the hello message</li>
876
+ <li><strong>Default variables are loaded</strong> from agent configuration (Redis)</li>
877
+ <li><strong>Variables are merged</strong> (hello variables take precedence)</li>
878
+ <li><strong>Prompt is processed</strong> - <code>{{VARIABLE_NAME}}</code> placeholders are replaced</li>
879
+ <li><strong>First message is processed</strong> - Variables are replaced here too</li>
880
+ <li><strong>Metadata is added</strong> - Variables metadata section is appended to prompt</li>
881
+ </ol>
882
+
883
+ <h3>Server Logs</h3>
884
+ <p>After sending hello with variables, check server logs for:</p>
885
+ <pre><code>📝 Processing variables from hello message: [USER_NAME, ACCOUNT_TYPE, LANGUAGE]
886
+ ✅ Variables processed and prompt updated
887
+ 📝 FINAL PROCESSED PROMPT (agentId: ...):
888
+ [Prompt with variables replaced]
889
+ ✅ Processed variables: 3 hello variables, 2 default variables, metadata: added</code></pre>
890
+
891
+ <h2>Variable Naming Conventions</h2>
892
+ <ul>
893
+ <li>Use <strong>UPPERCASE</strong> with underscores: <code>USER_NAME</code>, <code>ACCOUNT_TYPE</code></li>
894
+ <li>Variable names are <strong>case-sensitive</strong></li>
895
+ <li>Avoid special characters except underscores</li>
896
+ <li>Recommended format: <code>{{VARIABLE_NAME}}</code> in prompts</li>
897
+ </ul>
898
+
899
+ <h2>Common Use Cases</h2>
900
+
901
+ <h3>1. User Personalization</h3>
902
+ <pre><code>{
903
+ "variables": {
904
+ "USER_NAME": "John Doe",
905
+ "USER_EMAIL": "john@example.com"
906
+ }
907
+ }</code></pre>
908
+
909
+ <h3>2. Account Context</h3>
910
+ <pre><code>{
911
+ "variables": {
912
+ "ACCOUNT_TYPE": "premium",
913
+ "SUBSCRIPTION_STATUS": "active"
914
+ }
915
+ }</code></pre>
916
+
917
+ <h3>3. Language/Localization</h3>
918
+ <pre><code>{
919
+ "variables": {
920
+ "LANGUAGE": "en-US",
921
+ "CURRENCY": "USD"
922
+ }
923
+ }</code></pre>
924
+
925
+ <h3>4. Session Context</h3>
926
+ <pre><code>{
927
+ "variables": {
928
+ "SESSION_ID": "abc123",
929
+ "PAGE_URL": "https://example.com/products"
930
+ }
931
+ }</code></pre>
932
+
933
+ <h2>Error Handling</h2>
934
+
935
+ <h3>Missing Variables</h3>
936
+ <p>If a variable is referenced in the prompt but not provided:</p>
937
+ <ul>
938
+ <li><strong>Has default value</strong>: Uses default from agent configuration</li>
939
+ <li><strong>No default value</strong>: Placeholder remains unchanged (<code>{{VARIABLE_NAME}}</code>)</li>
940
+ </ul>
941
+
942
+ <h3>Invalid Variable Format</h3>
943
+ <ul>
944
+ <li>Variables must be a JSON object</li>
945
+ <li>Values should be strings (will be converted to string if needed)</li>
946
+ <li>Empty object <code>{}</code> or <code>null</code> is valid (will use defaults only)</li>
947
+ </ul>
948
+
949
+ <h2>Best Practices</h2>
950
+ <ol>
951
+ <li><strong>Set defaults</strong> in agent configuration for all variables</li>
952
+ <li><strong>Override with hello variables</strong> only when you have dynamic values</li>
953
+ <li><strong>Use descriptive names</strong> that clearly indicate the variable's purpose</li>
954
+ <li><strong>Document variables</strong> in your agent's description or notes</li>
955
+ <li><strong>Test variables</strong> by checking server logs for "FINAL PROCESSED PROMPT"</li>
956
+ </ol>
957
+
958
+ <h2>API Reference</h2>
959
+
960
+ <h3>Hello Message Structure</h3>
961
+ <pre><code>interface HelloMessage {
962
+ t: "hello"; // Message type
963
+ v?: number; // SDK version (2 for v2)
964
+ variables?: { // Optional variables object
965
+ [key: string]: string; // Variable name -> value mapping
966
+ };
967
+ inputFormat?: AudioFormat; // Input audio format
968
+ requestedOutputFormat?: AudioFormat; // Output audio format
969
+ outputFrameDurationMs?: number; // Frame duration for streaming
970
+ }
971
+
972
+ interface AudioFormat {
973
+ encoding: "pcm" | "pcmu" | "pcma";
974
+ sampleRate: number;
975
+ channels: number;
976
+ bitDepth: number;
977
+ container?: "raw" | "wav"; // For output format only
978
+ }</code></pre>
979
+
980
+ <h2>Troubleshooting</h2>
981
+
982
+ <h3>Variables Not Being Replaced</h3>
983
+ <ol>
984
+ <li>Check variable names match exactly (case-sensitive)</li>
985
+ <li>Verify variables are sent in hello message (check logs)</li>
986
+ <li>Check server logs for "FINAL PROCESSED PROMPT" to see actual replacement</li>
987
+ </ol>
988
+
989
+ <h3>Variables Not in Hello Message</h3>
990
+ <ul>
991
+ <li>SDK v2: Check if SDK supports <code>variables</code> in constructor</li>
992
+ <li>Raw WebSocket: Ensure <code>variables</code> field is included in JSON</li>
993
+ <li>Check WebSocket message is sent after connection opens</li>
994
+ </ul>
995
+
996
+ <h3>Default Variables Not Used</h3>
997
+ <ul>
998
+ <li>Verify variables are stored in Redis (check agent configuration)</li>
999
+ <li>Check <code>extractVariablesFromAgentConfig</code> is working</li>
1000
+ <li>Look for "Default variables not found in state" warnings in logs</li>
1001
+ </ul>
1002
+ </section>
1003
+
638
1004
  <!-- Events -->
639
1005
  <section id="events" class="doc-section">
640
1006
  <h1>Events & Callbacks</h1>
@@ -823,7 +1189,7 @@ voiceSDK.on('domainError', (error) => {
823
1189
 
824
1190
  <h2>Example: High-Quality Audio</h2>
825
1191
  <pre><code>const voiceSDK = new VoiceSDK({
826
- websocketUrl: signedUrl,
1192
+ signedUrl: signedUrl, // signedUrl from backend
827
1193
  appId: 'your_app_id',
828
1194
  agentId: 'agent_123',
829
1195
 
@@ -845,7 +1211,7 @@ voiceSDK.on('formatNegotiated', (format) => {
845
1211
 
846
1212
  <h2>Example: Bandwidth-Optimized Audio</h2>
847
1213
  <pre><code>const voiceSDK = new VoiceSDK({
848
- websocketUrl: signedUrl,
1214
+ signedUrl: signedUrl, // signedUrl from backend
849
1215
  appId: 'your_app_id',
850
1216
  agentId: 'agent_123',
851
1217
 
@@ -927,6 +1293,20 @@ voiceSDK.on('formatNegotiated', (format) => {
927
1293
  agentId: 'agent_123', // Your AI agent ID
928
1294
  appId: 'your_app_id', // Your application ID
929
1295
 
1296
+ // Optional - Signed URL (recommended for production)
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)
1300
+ agentSettingsOverride: {
1301
+ prompt: "You are a helpful customer service assistant.",
1302
+ temperature: 0.8,
1303
+ voiceId: "F2",
1304
+ voiceSpeed: 1.2,
1305
+ firstMessage: "Hello! How can I help you today?",
1306
+ disableInterruptions: false,
1307
+ maxCallDuration: 600
1308
+ },
1309
+
930
1310
  // Optional - Appearance
931
1311
  primaryColor: '#7C3AED', // Widget theme color
932
1312
  position: 'bottom-right', // 'bottom-right', 'bottom-left'
@@ -941,6 +1321,106 @@ voiceSDK.on('formatNegotiated', (format) => {
941
1321
  }
942
1322
  });</code></pre>
943
1323
 
1324
+ <h2>Signed Link Authentication (Production)</h2>
1325
+ <div class="warning-box">
1326
+ <strong>🔒 Security Best Practice:</strong> For production applications, use signed links instead of exposing agent IDs directly. Signed links provide secure, time-limited authentication.
1327
+ </div>
1328
+
1329
+ <p>To use signed links with the widget, provide a <code>signedUrl</code> parameter. You should fetch this signed URL from your backend before initializing the widget:</p>
1330
+
1331
+ <pre><code>// Step 1: Get signed URL from your backend
1332
+ async function initializeWidget() {
1333
+ // Request signed URL from your backend
1334
+ const response = await fetch('/api/get-voice-session', {
1335
+ method: 'POST',
1336
+ headers: {
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');
1359
+ }
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>
1375
+
1376
+ <div class="info-box">
1377
+ <strong>📋 Important:</strong>
1378
+ <ul style="margin-top: 10px; margin-left: 20px;">
1379
+ <li>The widget accepts <code>signedUrl</code> as a direct parameter (not <code>getSessionUrl</code>)</li>
1380
+ <li>You must fetch the signed URL from your backend before initializing the widget</li>
1381
+ <li>Your backend must return a response with a <code>signedUrl</code> field (not <code>websocketUrl</code>, <code>url</code>, or any other field)</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>
1384
+ </ul>
1385
+ </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
+
944
1424
  <h2>Advanced Customization</h2>
945
1425
 
946
1426
  <h3>Icon Customization</h3>
@@ -984,6 +1464,39 @@ voiceSDK.on('formatNegotiated', (format) => {
984
1464
  }
985
1465
  });</code></pre>
986
1466
 
1467
+ <h3>Agent Settings Override</h3>
1468
+ <div class="info-box">
1469
+ <strong>🔒 Security:</strong> Agent settings override requires a signed URL with <code>allowOverride: true</code> granted by your backend.
1470
+ </div>
1471
+ <p>Dynamically customize agent behavior, voice, and personality on a per-session basis:</p>
1472
+ <pre><code>const widget = new TTPAgentSDK.TTPChatWidget({
1473
+ agentId: 'agent_123',
1474
+ appId: 'your_app_id',
1475
+ signedUrl: 'wss://speech.talktopc.com/ws/conv?signed_token=...', // Required: signed URL with allowOverride=true
1476
+
1477
+ // Override agent settings dynamically
1478
+ agentSettingsOverride: {
1479
+ // Core settings
1480
+ prompt: "You are a friendly customer service assistant",
1481
+ temperature: 0.8,
1482
+ maxTokens: 200,
1483
+
1484
+ // Voice settings
1485
+ voiceId: "F2",
1486
+ voiceSpeed: 1.2,
1487
+
1488
+ // Behavior
1489
+ firstMessage: "Hello! How can I help you today?",
1490
+ disableInterruptions: false,
1491
+ maxCallDuration: 600,
1492
+
1493
+ // Language
1494
+ language: "en",
1495
+ autoDetectLanguage: false
1496
+ }
1497
+ });</code></pre>
1498
+ <p>See the <a href="#agent-override">Agent Settings Override</a> section for complete documentation of all available override settings.</p>
1499
+
987
1500
  <h3>RTL (Right-to-Left) Support</h3>
988
1501
  <pre><code>// For Hebrew, Arabic, etc.
989
1502
  const widget = new TTPAgentSDK.TTPChatWidget({
@@ -1182,6 +1695,18 @@ document.getElementById('myButton').onclick = () => {
1182
1695
  <td>{}</td>
1183
1696
  <td>Custom variables to pass to agent</td>
1184
1697
  </tr>
1698
+ <tr>
1699
+ <td><code>signedUrl</code></td>
1700
+ <td>string | function</td>
1701
+ <td>null</td>
1702
+ <td>Signed URL for secure authentication (string or async function that returns URL)</td>
1703
+ </tr>
1704
+ <tr>
1705
+ <td><code>agentSettingsOverride</code></td>
1706
+ <td>object</td>
1707
+ <td>null</td>
1708
+ <td>Override agent settings dynamically (requires signed URL with allowOverride=true). See <a href="#agent-override">Agent Settings Override</a> for details.</td>
1709
+ </tr>
1185
1710
  <tr>
1186
1711
  <td><code>customStyles</code></td>
1187
1712
  <td>string</td>
@@ -1867,16 +2392,10 @@ document.getElementById('myButton').onclick = () => {
1867
2392
  </thead>
1868
2393
  <tbody>
1869
2394
  <tr>
1870
- <td><code>websocketUrl</code></td>
1871
- <td>string</td>
1872
- <td>Auto-detected</td>
1873
- <td>Custom WebSocket URL for text chat</td>
1874
- </tr>
1875
- <tr>
1876
- <td><code>voice.websocketUrl</code></td>
2395
+ <td><code>signedUrl</code></td>
1877
2396
  <td>string</td>
1878
- <td>Auto-detected</td>
1879
- <td>Custom WebSocket URL for voice chat</td>
2397
+ <td>Optional</td>
2398
+ <td>Signed WebSocket URL for secure authentication (for voice). If not provided, URL is constructed from agentId/appId.</td>
1880
2399
  </tr>
1881
2400
  <tr>
1882
2401
  <td><code>demo</code></td>
@@ -2005,7 +2524,7 @@ class VoiceAssistant {
2005
2524
 
2006
2525
  // Step 2: Create SDK
2007
2526
  this.sdk = new VoiceSDK({
2008
- websocketUrl: signedUrl,
2527
+ signedUrl: signedUrl, // signedUrl from backend
2009
2528
  appId: 'your_app_id',
2010
2529
  agentId: agentId,
2011
2530
  agentSettingsOverride: overrides
@@ -2138,7 +2657,7 @@ function VoiceChat() {
2138
2657
 
2139
2658
  // Create SDK
2140
2659
  const sdk = new VoiceSDK({
2141
- websocketUrl: signedUrl,
2660
+ signedUrl: signedUrl, // signedUrl from backend
2142
2661
  appId: 'your_app_id',
2143
2662
  agentId: 'agent_123',
2144
2663
  agentSettingsOverride: {
@@ -2240,7 +2759,7 @@ function App() {
2240
2759
 
2241
2760
  return (
2242
2761
  &lt;VoiceButton
2243
- websocketUrl={signedUrl}
2762
+ signedUrl={signedUrl} {/* signedUrl from backend */}
2244
2763
  appId="your_app_id"
2245
2764
  agentId="agent_123"
2246
2765
  agentSettingsOverride={{
@@ -2266,7 +2785,7 @@ function App() {
2266
2785
  </thead>
2267
2786
  <tbody>
2268
2787
  <tr>
2269
- <td><code>websocketUrl</code></td>
2788
+ <td><code>signedUrl</code></td>
2270
2789
  <td>string</td>
2271
2790
  <td>Yes</td>
2272
2791
  <td>Signed WebSocket URL</td>
@@ -2412,7 +2931,7 @@ function App() {
2412
2931
  </thead>
2413
2932
  <tbody>
2414
2933
  <tr>
2415
- <td><code>websocketUrl</code></td>
2934
+ <td><code>signedUrl</code></td>
2416
2935
  <td>string</td>
2417
2936
  <td>Yes</td>
2418
2937
  <td>Signed WebSocket URL from your backend</td>
@@ -2534,7 +3053,7 @@ function App() {
2534
3053
 
2535
3054
  <h4>Example: Custom Audio Format</h4>
2536
3055
  <pre><code>const voiceSDK = new VoiceSDK({
2537
- websocketUrl: signedUrl,
3056
+ signedUrl: signedUrl, // signedUrl from backend
2538
3057
  appId: 'your_app_id',
2539
3058
  agentId: 'agent_123',
2540
3059
 
@@ -3404,6 +3923,20 @@ app.post('/api/generate-speech', async (req, res) => {
3404
3923
  &lt;/dependency&gt;
3405
3924
  &lt;/dependencies&gt;</code></pre>
3406
3925
 
3926
+ <div class="warning-box">
3927
+ <strong>⚠️ GitHub Packages Authentication:</strong>
3928
+ <p>You'll need to authenticate with GitHub Packages. Add credentials to your <code>~/.m2/settings.xml</code>:</p>
3929
+ <pre><code>&lt;settings&gt;
3930
+ &lt;servers&gt;
3931
+ &lt;server&gt;
3932
+ &lt;id&gt;github&lt;/id&gt;
3933
+ &lt;username&gt;YOUR_GITHUB_USERNAME&lt;/username&gt;
3934
+ &lt;password&gt;YOUR_GITHUB_TOKEN&lt;/password&gt;
3935
+ &lt;/server&gt;
3936
+ &lt;/servers&gt;
3937
+ &lt;/settings&gt;</code></pre>
3938
+ </div>
3939
+
3407
3940
  <h3>Gradle</h3>
3408
3941
  <pre><code>repositories {
3409
3942
  maven {
@@ -3429,6 +3962,7 @@ String apiKey = System.getenv("TALKTOPC_API_KEY");
3429
3962
 
3430
3963
  VoiceSDK sdk = VoiceSDK.builder()
3431
3964
  .apiKey(apiKey)
3965
+ .baseUrl("https://api.talktopc.com") // Optional
3432
3966
  .build();</code></pre>
3433
3967
 
3434
3968
  <h3>2. Simple TTS (Blocking)</h3>
@@ -3858,4 +4392,3 @@ Files.write(Paths.get("output.wav"), response.getAudio());</code></pre>
3858
4392
  </html>
3859
4393
 
3860
4394
 
3861
- <!-- Cloudflare Pages rebuild trigger -->