ttp-agent-sdk 2.0.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.
@@ -0,0 +1,429 @@
1
+ # Getting Started with TTP Agent SDK
2
+
3
+ This guide will help you quickly integrate voice AI agents into your web application using the TTP Agent SDK.
4
+
5
+ ## Quick Start
6
+
7
+ ### 1. Installation
8
+
9
+ ```bash
10
+ npm install ttp-agent-sdk
11
+ ```
12
+
13
+ ### 2. Basic Usage
14
+
15
+ #### Option A: Pre-built Widget (Easiest)
16
+
17
+ ```html
18
+ <!DOCTYPE html>
19
+ <html>
20
+ <head>
21
+ <title>Voice Agent Demo</title>
22
+ </head>
23
+ <body>
24
+ <!-- Your app content -->
25
+
26
+ <!-- Load the SDK -->
27
+ <script src="https://unpkg.com/ttp-agent-sdk/dist/agent-widget.js"></script>
28
+
29
+ <script>
30
+ // Initialize the voice widget
31
+ TTPAgentSDK.AgentWidget.init({
32
+ agentId: 'your_agent_id',
33
+ getSessionUrl: async ({ agentId, variables }) => {
34
+ const response = await fetch('/api/get-session', {
35
+ method: 'POST',
36
+ headers: { 'Content-Type': 'application/json' },
37
+ body: JSON.stringify({ agentId, variables })
38
+ });
39
+ const data = await response.json();
40
+ return data.signedUrl;
41
+ }
42
+ });
43
+ </script>
44
+ </body>
45
+ </html>
46
+ ```
47
+
48
+ #### Option B: React Component
49
+
50
+ ```jsx
51
+ import React from 'react';
52
+ import { VoiceButton } from 'ttp-agent-sdk';
53
+
54
+ function App() {
55
+ return (
56
+ <VoiceButton
57
+ websocketUrl="wss://speech.bidme.co.il/ws/conv"
58
+ agentId="your_agent_id"
59
+ appId="your_app_id"
60
+ onConnected={() => console.log('Connected!')}
61
+ onRecordingStarted={() => console.log('Recording...')}
62
+ />
63
+ );
64
+ }
65
+ ```
66
+
67
+ #### Option C: Vanilla JavaScript
68
+
69
+ ```javascript
70
+ import { VoiceSDK } from 'ttp-agent-sdk';
71
+
72
+ const voiceSDK = new VoiceSDK({
73
+ websocketUrl: 'wss://speech.bidme.co.il/ws/conv',
74
+ agentId: 'your_agent_id',
75
+ appId: 'your_app_id'
76
+ });
77
+
78
+ // Connect and start recording
79
+ await voiceSDK.connect();
80
+ await voiceSDK.startRecording();
81
+ ```
82
+
83
+ ## Authentication Methods
84
+
85
+ ### Method 1: Direct Agent ID (Development)
86
+
87
+ For development and testing, you can use direct agent ID authentication:
88
+
89
+ ```javascript
90
+ const voiceSDK = new VoiceSDK({
91
+ websocketUrl: 'wss://speech.bidme.co.il/ws/conv',
92
+ agentId: 'your_agent_id', // Direct agent ID
93
+ appId: 'your_app_id' // User's app ID
94
+ });
95
+ ```
96
+
97
+ **Note**: This method is unsecured as the agent ID is visible in network traffic.
98
+
99
+ ### Method 2: Signed Link (Production)
100
+
101
+ For production applications, use signed link authentication:
102
+
103
+ ```javascript
104
+ const voiceSDK = new VoiceSDK({
105
+ websocketUrl: 'wss://speech.bidme.co.il/ws/conv?signed_token=eyJ...'
106
+ // No agentId needed - server validates signed token
107
+ });
108
+ ```
109
+
110
+ To get a signed URL from your backend:
111
+
112
+ ```javascript
113
+ async function getSignedUrl(agentId, variables = {}) {
114
+ const response = await fetch('/api/get-session', {
115
+ method: 'POST',
116
+ headers: { 'Content-Type': 'application/json' },
117
+ body: JSON.stringify({ agentId, variables })
118
+ });
119
+ const data = await response.json();
120
+ return data.signedUrl;
121
+ }
122
+ ```
123
+
124
+ ## Configuration Options
125
+
126
+ ### VoiceSDK Configuration
127
+
128
+ ```javascript
129
+ const voiceSDK = new VoiceSDK({
130
+ websocketUrl: 'wss://speech.bidme.co.il/ws/conv', // Required
131
+ agentId: 'agent_12345', // Optional - for direct access
132
+ appId: 'app_67890', // Optional - user's app ID
133
+ ttpId: 'ttp_abc123', // Optional - custom TTP ID
134
+ voice: 'default', // Optional - voice selection
135
+ language: 'en', // Optional - language code
136
+ sampleRate: 16000, // Optional - audio sample rate
137
+ autoReconnect: true // Optional - auto-reconnect
138
+ });
139
+ ```
140
+
141
+ ### Widget Configuration
142
+
143
+ ```javascript
144
+ TTPAgentSDK.AgentWidget.init({
145
+ agentId: 'your_agent_id', // Required
146
+ getSessionUrl: 'https://...', // Required - URL or function
147
+ variables: { // Optional - dynamic variables
148
+ userName: 'John Doe',
149
+ page: 'homepage'
150
+ },
151
+ position: 'bottom-right', // Optional - widget position
152
+ primaryColor: '#4F46E5' // Optional - theme color
153
+ });
154
+ ```
155
+
156
+ ## Event Handling
157
+
158
+ The SDK provides comprehensive event handling:
159
+
160
+ ```javascript
161
+ voiceSDK.on('connected', () => {
162
+ console.log('Connected to voice agent');
163
+ });
164
+
165
+ voiceSDK.on('disconnected', () => {
166
+ console.log('Disconnected from voice agent');
167
+ });
168
+
169
+ voiceSDK.on('recordingStarted', () => {
170
+ console.log('Recording started');
171
+ });
172
+
173
+ voiceSDK.on('recordingStopped', () => {
174
+ console.log('Recording stopped');
175
+ });
176
+
177
+ voiceSDK.on('playbackStarted', () => {
178
+ console.log('Agent is speaking');
179
+ });
180
+
181
+ voiceSDK.on('playbackStopped', () => {
182
+ console.log('Agent finished speaking');
183
+ });
184
+
185
+ voiceSDK.on('message', (message) => {
186
+ if (message.type === 'agent_response') {
187
+ console.log('Agent response:', message.agent_response);
188
+ } else if (message.type === 'user_transcript') {
189
+ console.log('User said:', message.user_transcription);
190
+ }
191
+ });
192
+
193
+ voiceSDK.on('error', (error) => {
194
+ console.error('VoiceSDK Error:', error);
195
+ });
196
+ ```
197
+
198
+ ## Backend Integration
199
+
200
+ ### Required Backend Endpoint
201
+
202
+ Your backend needs to provide a session endpoint that returns a signed WebSocket URL:
203
+
204
+ ```javascript
205
+ // Example Express.js endpoint
206
+ app.post('/api/get-session', async (req, res) => {
207
+ const { agentId, variables } = req.body;
208
+
209
+ // Validate user authentication
210
+ const user = await authenticateUser(req);
211
+ if (!user) {
212
+ return res.status(401).json({ error: 'Unauthorized' });
213
+ }
214
+
215
+ // Generate signed URL
216
+ const signedUrl = await generateSignedUrl({
217
+ agentId,
218
+ userId: user.id,
219
+ appId: user.appId,
220
+ variables
221
+ });
222
+
223
+ res.json({ signedUrl });
224
+ });
225
+ ```
226
+
227
+ ### Signed URL Generation
228
+
229
+ The signed URL should contain a JWT token with the following claims:
230
+
231
+ ```javascript
232
+ const jwt = require('jsonwebtoken');
233
+
234
+ function generateSignedUrl({ agentId, userId, appId, variables }) {
235
+ const token = jwt.sign({
236
+ agentId,
237
+ userId,
238
+ appId,
239
+ variables,
240
+ exp: Math.floor(Date.now() / 1000) + (60 * 60) // 1 hour expiry
241
+ }, process.env.CONVERSATION_SECRET_KEY);
242
+
243
+ return `wss://speech.bidme.co.il/ws/conv?signed_token=${token}`;
244
+ }
245
+ ```
246
+
247
+ ## Examples
248
+
249
+ ### Complete React Example
250
+
251
+ ```jsx
252
+ import React, { useState, useEffect, useRef } from 'react';
253
+ import { VoiceSDK } from 'ttp-agent-sdk';
254
+
255
+ function VoiceChat() {
256
+ const [isConnected, setIsConnected] = useState(false);
257
+ const [isRecording, setIsRecording] = useState(false);
258
+ const [messages, setMessages] = useState([]);
259
+ const voiceSDKRef = useRef(null);
260
+
261
+ useEffect(() => {
262
+ const voiceSDK = new VoiceSDK({
263
+ websocketUrl: 'wss://speech.bidme.co.il/ws/conv',
264
+ agentId: 'your_agent_id',
265
+ appId: 'your_app_id'
266
+ });
267
+
268
+ voiceSDK.on('connected', () => setIsConnected(true));
269
+ voiceSDK.on('disconnected', () => setIsConnected(false));
270
+ voiceSDK.on('recordingStarted', () => setIsRecording(true));
271
+ voiceSDK.on('recordingStopped', () => setIsRecording(false));
272
+ voiceSDK.on('message', (message) => {
273
+ if (message.type === 'agent_response') {
274
+ setMessages(prev => [...prev, { type: 'agent', text: message.agent_response }]);
275
+ }
276
+ });
277
+
278
+ voiceSDKRef.current = voiceSDK;
279
+
280
+ return () => voiceSDK.destroy();
281
+ }, []);
282
+
283
+ const handleConnect = async () => {
284
+ await voiceSDKRef.current.connect();
285
+ };
286
+
287
+ const handleToggleRecording = async () => {
288
+ if (isRecording) {
289
+ await voiceSDKRef.current.stopRecording();
290
+ } else {
291
+ await voiceSDKRef.current.startRecording();
292
+ }
293
+ };
294
+
295
+ return (
296
+ <div>
297
+ <button onClick={handleConnect} disabled={isConnected}>
298
+ Connect
299
+ </button>
300
+ <button onClick={handleToggleRecording} disabled={!isConnected}>
301
+ {isRecording ? 'Stop Recording' : 'Start Recording'}
302
+ </button>
303
+ <div>
304
+ {messages.map((msg, i) => (
305
+ <div key={i}>{msg.type}: {msg.text}</div>
306
+ ))}
307
+ </div>
308
+ </div>
309
+ );
310
+ }
311
+ ```
312
+
313
+ ### Complete Vanilla JavaScript Example
314
+
315
+ ```html
316
+ <!DOCTYPE html>
317
+ <html>
318
+ <head>
319
+ <title>Voice Chat</title>
320
+ </head>
321
+ <body>
322
+ <button id="connectBtn">Connect</button>
323
+ <button id="recordBtn" disabled>Start Recording</button>
324
+ <div id="messages"></div>
325
+
326
+ <script type="module">
327
+ import { VoiceSDK } from 'https://unpkg.com/ttp-agent-sdk/dist/agent-widget.js';
328
+
329
+ const voiceSDK = new VoiceSDK({
330
+ websocketUrl: 'wss://speech.bidme.co.il/ws/conv',
331
+ agentId: 'your_agent_id',
332
+ appId: 'your_app_id'
333
+ });
334
+
335
+ let isRecording = false;
336
+
337
+ voiceSDK.on('connected', () => {
338
+ document.getElementById('connectBtn').disabled = true;
339
+ document.getElementById('recordBtn').disabled = false;
340
+ });
341
+
342
+ voiceSDK.on('recordingStarted', () => {
343
+ isRecording = true;
344
+ document.getElementById('recordBtn').textContent = 'Stop Recording';
345
+ });
346
+
347
+ voiceSDK.on('recordingStopped', () => {
348
+ isRecording = false;
349
+ document.getElementById('recordBtn').textContent = 'Start Recording';
350
+ });
351
+
352
+ voiceSDK.on('message', (message) => {
353
+ if (message.type === 'agent_response') {
354
+ addMessage('Agent', message.agent_response);
355
+ }
356
+ });
357
+
358
+ document.getElementById('connectBtn').onclick = () => voiceSDK.connect();
359
+ document.getElementById('recordBtn').onclick = () => {
360
+ if (isRecording) {
361
+ voiceSDK.stopRecording();
362
+ } else {
363
+ voiceSDK.startRecording();
364
+ }
365
+ };
366
+
367
+ function addMessage(sender, text) {
368
+ const div = document.createElement('div');
369
+ div.textContent = `${sender}: ${text}`;
370
+ document.getElementById('messages').appendChild(div);
371
+ }
372
+ </script>
373
+ </body>
374
+ </html>
375
+ ```
376
+
377
+ ## Troubleshooting
378
+
379
+ ### Common Issues
380
+
381
+ 1. **Connection Failed**
382
+ - Check if the WebSocket URL is correct
383
+ - Verify agent ID and app ID are valid
384
+ - Ensure backend is running and accessible
385
+
386
+ 2. **Microphone Access Denied**
387
+ - Request microphone permission in browser
388
+ - Use HTTPS in production (required for microphone access)
389
+
390
+ 3. **Audio Not Playing**
391
+ - Check browser audio settings
392
+ - Ensure Web Audio API is supported
393
+ - Verify audio format compatibility
394
+
395
+ 4. **Authentication Errors**
396
+ - Verify signed token is valid and not expired
397
+ - Check secret key configuration
398
+ - Ensure agent ID exists in backend
399
+
400
+ ### Debug Mode
401
+
402
+ Enable debug logging:
403
+
404
+ ```javascript
405
+ const voiceSDK = new VoiceSDK({
406
+ // ... config
407
+ debug: true // Enable debug logging
408
+ });
409
+ ```
410
+
411
+ ## Browser Support
412
+
413
+ - Chrome 66+
414
+ - Firefox 60+
415
+ - Safari 11.1+
416
+ - Edge 79+
417
+
418
+ ## Next Steps
419
+
420
+ - Check out the [examples](./examples/) directory for more complete examples
421
+ - Read the [API Reference](./README.md#api-reference) for detailed documentation
422
+ - Join our community for support and updates
423
+
424
+ ## Support
425
+
426
+ For support and questions:
427
+ - Open an issue on GitHub
428
+ - Contact our support team
429
+ - Check the documentation