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/agent-widget.js +1 -1
- package/dist/agent-widget.js.map +1 -1
- package/dist/audio-processor.js +1 -1
- package/dist/examples/test-signed-link.html +134 -115
- package/dist/index.html +561 -28
- package/examples/test-signed-link.html +134 -115
- package/package.json +1 -1
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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>
|
|
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>
|
|
1879
|
-
<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
|
-
|
|
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
|
-
|
|
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
|
<VoiceButton
|
|
2243
|
-
|
|
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>
|
|
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>
|
|
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
|
-
|
|
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
|
</dependency>
|
|
3405
3924
|
</dependencies></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><settings>
|
|
3930
|
+
<servers>
|
|
3931
|
+
<server>
|
|
3932
|
+
<id>github</id>
|
|
3933
|
+
<username>YOUR_GITHUB_USERNAME</username>
|
|
3934
|
+
<password>YOUR_GITHUB_TOKEN</password>
|
|
3935
|
+
</server>
|
|
3936
|
+
</servers>
|
|
3937
|
+
</settings></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 -->
|