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,455 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>React VoiceSDK Example</title>
7
+ <style>
8
+ body {
9
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
10
+ max-width: 1000px;
11
+ margin: 0 auto;
12
+ padding: 20px;
13
+ background: #F9FAFB;
14
+ }
15
+
16
+ .container {
17
+ background: white;
18
+ padding: 30px;
19
+ border-radius: 12px;
20
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
21
+ margin-bottom: 20px;
22
+ }
23
+
24
+ h1 {
25
+ color: #111827;
26
+ margin-top: 0;
27
+ }
28
+
29
+ .info {
30
+ background: #EFF6FF;
31
+ border-left: 4px solid #3B82F6;
32
+ padding: 16px;
33
+ margin: 20px 0;
34
+ border-radius: 4px;
35
+ }
36
+
37
+ .code-block {
38
+ background: #1F2937;
39
+ color: #F9FAFB;
40
+ padding: 20px;
41
+ border-radius: 8px;
42
+ font-family: 'Monaco', 'Menlo', monospace;
43
+ font-size: 14px;
44
+ overflow-x: auto;
45
+ margin: 20px 0;
46
+ }
47
+
48
+ .note {
49
+ background: #FEF3C7;
50
+ border-left: 4px solid #F59E0B;
51
+ padding: 16px;
52
+ margin: 20px 0;
53
+ border-radius: 4px;
54
+ }
55
+
56
+ .back-link {
57
+ display: inline-block;
58
+ background: #4F46E5;
59
+ color: white;
60
+ padding: 12px 24px;
61
+ text-decoration: none;
62
+ border-radius: 8px;
63
+ font-weight: 600;
64
+ margin-bottom: 20px;
65
+ }
66
+
67
+ .back-link:hover {
68
+ background: #4338CA;
69
+ }
70
+ </style>
71
+ </head>
72
+ <body>
73
+ <a href="../index.html" class="back-link">← Back to SDK Home</a>
74
+
75
+ <div class="container">
76
+ <h1>âš›ī¸ React VoiceSDK Example</h1>
77
+
78
+ <div class="info">
79
+ <strong>Note:</strong> This is a code example showing how to integrate the VoiceSDK with React.
80
+ To run this example, you'll need a React development environment.
81
+ </div>
82
+
83
+ <h2>Installation</h2>
84
+ <div class="code-block">
85
+ npm install ttp-agent-sdk react react-dom
86
+ </div>
87
+
88
+ <h2>Basic React Component</h2>
89
+ <div class="code-block">
90
+ import React, { useState, useEffect, useRef } from 'react';
91
+ import { VoiceSDK } from 'ttp-agent-sdk';
92
+
93
+ function VoiceChat() {
94
+ const [isConnected, setIsConnected] = useState(false);
95
+ const [isRecording, setIsRecording] = useState(false);
96
+ const [messages, setMessages] = useState([]);
97
+ const voiceSDKRef = useRef(null);
98
+
99
+ useEffect(() => {
100
+ const voiceSDK = new VoiceSDK({
101
+ websocketUrl: 'wss://speech.bidme.co.il/ws/conv',
102
+ agentId: 'your_agent_id',
103
+ appId: 'your_app_id'
104
+ });
105
+
106
+ voiceSDK.on('connected', () => setIsConnected(true));
107
+ voiceSDK.on('disconnected', () => setIsConnected(false));
108
+ voiceSDK.on('recordingStarted', () => setIsRecording(true));
109
+ voiceSDK.on('recordingStopped', () => setIsRecording(false));
110
+ voiceSDK.on('message', (message) => {
111
+ if (message.type === 'agent_response') {
112
+ setMessages(prev => [...prev, { type: 'agent', text: message.agent_response }]);
113
+ }
114
+ });
115
+
116
+ voiceSDKRef.current = voiceSDK;
117
+
118
+ return () => voiceSDK.destroy();
119
+ }, []);
120
+
121
+ const handleConnect = async () => {
122
+ await voiceSDKRef.current.connect();
123
+ };
124
+
125
+ const handleToggleRecording = async () => {
126
+ if (isRecording) {
127
+ await voiceSDKRef.current.stopRecording();
128
+ } else {
129
+ await voiceSDKRef.current.startRecording();
130
+ }
131
+ };
132
+
133
+ return (
134
+ &lt;div&gt;
135
+ &lt;button onClick={handleConnect} disabled={isConnected}&gt;
136
+ Connect
137
+ &lt;/button&gt;
138
+ &lt;button onClick={handleToggleRecording} disabled={!isConnected}&gt;
139
+ {isRecording ? 'Stop Recording' : 'Start Recording'}
140
+ &lt;/button&gt;
141
+ &lt;div&gt;
142
+ {messages.map((msg, i) => (
143
+ &lt;div key={i}&gt;{msg.type}: {msg.text}&lt;/div&gt;
144
+ ))}
145
+ &lt;/div&gt;
146
+ &lt;/div&gt;
147
+ );
148
+ }
149
+
150
+ export default VoiceChat;
151
+ </div>
152
+
153
+ <h2>Using the VoiceButton Component</h2>
154
+ <div class="code-block">
155
+ import React from 'react';
156
+ import { VoiceButton } from 'ttp-agent-sdk';
157
+
158
+ function App() {
159
+ return (
160
+ &lt;VoiceButton
161
+ websocketUrl="wss://speech.bidme.co.il/ws/conv"
162
+ agentId="your_agent_id"
163
+ appId="your_app_id"
164
+ onConnected={() => console.log('Connected!')}
165
+ onRecordingStarted={() => console.log('Recording...')}
166
+ onPlaybackStarted={() => console.log('Playing audio...')}
167
+ /&gt;
168
+ );
169
+ }
170
+
171
+ export default App;
172
+ </div>
173
+
174
+ <h2>Advanced React Integration</h2>
175
+ <div class="code-block">
176
+ import React, { useState, useEffect, useRef } from 'react';
177
+ import { VoiceSDK } from 'ttp-agent-sdk';
178
+
179
+ function AdvancedVoiceChat() {
180
+ const [isConnected, setIsConnected] = useState(false);
181
+ const [isRecording, setIsRecording] = useState(false);
182
+ const [isPlaying, setIsPlaying] = useState(false);
183
+ const [messages, setMessages] = useState([]);
184
+ const [connectionStatus, setConnectionStatus] = useState('Disconnected');
185
+
186
+ const voiceSDKRef = useRef(null);
187
+
188
+ useEffect(() => {
189
+ const voiceSDK = new VoiceSDK({
190
+ websocketUrl: 'wss://speech.bidme.co.il/ws/conv',
191
+ agentId: 'your_agent_id',
192
+ appId: 'your_app_id',
193
+ voice: 'default',
194
+ language: 'en',
195
+ autoReconnect: true
196
+ });
197
+
198
+ // Set up comprehensive event handlers
199
+ voiceSDK.on('connected', () => {
200
+ setIsConnected(true);
201
+ setConnectionStatus('Connected');
202
+ addMessage('system', 'Connected to voice agent');
203
+ });
204
+
205
+ voiceSDK.on('disconnected', () => {
206
+ setIsConnected(false);
207
+ setIsRecording(false);
208
+ setIsPlaying(false);
209
+ setConnectionStatus('Disconnected');
210
+ addMessage('system', 'Disconnected from voice agent');
211
+ });
212
+
213
+ voiceSDK.on('recordingStarted', () => {
214
+ setIsRecording(true);
215
+ addMessage('user', '🎤 Recording...');
216
+ });
217
+
218
+ voiceSDK.on('recordingStopped', () => {
219
+ setIsRecording(false);
220
+ addMessage('user', 'âšī¸ Recording stopped');
221
+ });
222
+
223
+ voiceSDK.on('playbackStarted', () => {
224
+ setIsPlaying(true);
225
+ addMessage('agent', '🔊 Agent is speaking...');
226
+ });
227
+
228
+ voiceSDK.on('playbackStopped', () => {
229
+ setIsPlaying(false);
230
+ });
231
+
232
+ voiceSDK.on('message', (message) => {
233
+ if (message.type === 'agent_response') {
234
+ addMessage('agent', message.agent_response);
235
+ } else if (message.type === 'user_transcript') {
236
+ addMessage('user', message.user_transcription);
237
+ }
238
+ });
239
+
240
+ voiceSDK.on('error', (error) => {
241
+ console.error('VoiceSDK Error:', error);
242
+ addMessage('error', `Error: ${error.message}`);
243
+ });
244
+
245
+ voiceSDKRef.current = voiceSDK;
246
+
247
+ return () => {
248
+ if (voiceSDKRef.current) {
249
+ voiceSDKRef.current.destroy();
250
+ }
251
+ };
252
+ }, []);
253
+
254
+ const addMessage = (type, text) => {
255
+ setMessages(prev => [...prev, { type, text, timestamp: new Date() }]);
256
+ };
257
+
258
+ const handleConnect = async () => {
259
+ if (voiceSDKRef.current) {
260
+ try {
261
+ setConnectionStatus('Connecting...');
262
+ await voiceSDKRef.current.connect();
263
+ } catch (error) {
264
+ console.error('Connection failed:', error);
265
+ setConnectionStatus('Connection failed');
266
+ }
267
+ }
268
+ };
269
+
270
+ const handleDisconnect = () => {
271
+ if (voiceSDKRef.current) {
272
+ voiceSDKRef.current.disconnect();
273
+ }
274
+ };
275
+
276
+ const handleToggleRecording = async () => {
277
+ if (voiceSDKRef.current) {
278
+ try {
279
+ if (isRecording) {
280
+ await voiceSDKRef.current.stopRecording();
281
+ } else {
282
+ await voiceSDKRef.current.startRecording();
283
+ }
284
+ } catch (error) {
285
+ console.error('Recording toggle failed:', error);
286
+ }
287
+ }
288
+ };
289
+
290
+ return (
291
+ &lt;div style={{ maxWidth: '800px', margin: '0 auto', padding: '20px' }}&gt;
292
+ &lt;h1&gt;🎤 Voice Chat App&lt;/h1&gt;
293
+
294
+ &lt;div style={{
295
+ padding: '12px',
296
+ borderRadius: '8px',
297
+ marginBottom: '20px',
298
+ backgroundColor: isConnected ? '#D1FAE5' : '#FEE2E2',
299
+ color: isConnected ? '#065F46' : '#991B1B',
300
+ border: `1px solid ${isConnected ? '#10B981' : '#EF4444'}`
301
+ }}&gt;
302
+ &lt;strong&gt;Status:&lt;/strong&gt; {connectionStatus}
303
+ &lt;/div&gt;
304
+
305
+ &lt;div style={{ display: 'flex', gap: '12px', marginBottom: '20px' }}&gt;
306
+ &lt;button
307
+ onClick={handleConnect}
308
+ disabled={isConnected}
309
+ style={{
310
+ padding: '12px 24px',
311
+ backgroundColor: isConnected ? '#9CA3AF' : '#4F46E5',
312
+ color: 'white',
313
+ border: 'none',
314
+ borderRadius: '6px',
315
+ cursor: isConnected ? 'not-allowed' : 'pointer'
316
+ }}
317
+ &gt;
318
+ Connect
319
+ &lt;/button&gt;
320
+
321
+ &lt;button
322
+ onClick={handleDisconnect}
323
+ disabled={!isConnected}
324
+ style={{
325
+ padding: '12px 24px',
326
+ backgroundColor: !isConnected ? '#9CA3AF' : '#EF4444',
327
+ color: 'white',
328
+ border: 'none',
329
+ borderRadius: '6px',
330
+ cursor: !isConnected ? 'not-allowed' : 'pointer'
331
+ }}
332
+ &gt;
333
+ Disconnect
334
+ &lt;/button&gt;
335
+
336
+ &lt;button
337
+ onClick={handleToggleRecording}
338
+ disabled={!isConnected}
339
+ style={{
340
+ padding: '12px 24px',
341
+ backgroundColor: !isConnected ? '#9CA3AF' : (isRecording ? '#EF4444' : '#10B981'),
342
+ color: 'white',
343
+ border: 'none',
344
+ borderRadius: '6px',
345
+ cursor: !isConnected ? 'not-allowed' : 'pointer'
346
+ }}
347
+ &gt;
348
+ {isRecording ? 'Stop Recording' : 'Start Recording'}
349
+ &lt;/button&gt;
350
+ &lt;/div&gt;
351
+
352
+ &lt;div style={{
353
+ border: '1px solid #E5E7EB',
354
+ borderRadius: '8px',
355
+ height: '400px',
356
+ overflowY: 'auto',
357
+ padding: '16px',
358
+ backgroundColor: '#F9FAFB'
359
+ }}&gt;
360
+ &lt;h3&gt;Messages:&lt;/h3&gt;
361
+ {messages.length === 0 ? (
362
+ &lt;p style={{ color: '#6B7280', fontStyle: 'italic' }}&gt;
363
+ No messages yet. Connect and start recording to begin the conversation.
364
+ &lt;/p&gt;
365
+ ) : (
366
+ messages.map((message, index) => (
367
+ &lt;div
368
+ key={index}
369
+ style={{
370
+ marginBottom: '12px',
371
+ padding: '8px 12px',
372
+ borderRadius: '6px',
373
+ backgroundColor: message.type === 'user' ? '#E5E7EB' :
374
+ message.type === 'agent' ? '#F3F4F6' :
375
+ message.type === 'error' ? '#FEE2E2' : '#EFF6FF',
376
+ color: message.type === 'error' ? '#991B1B' : '#111827',
377
+ alignSelf: message.type === 'user' ? 'flex-end' : 'flex-start',
378
+ maxWidth: '80%',
379
+ marginLeft: message.type === 'user' ? 'auto' : '0',
380
+ marginRight: message.type === 'user' ? '0' : 'auto'
381
+ }}
382
+ &gt;
383
+ &lt;div style={{ fontWeight: 'bold', marginBottom: '4px' }}&gt;
384
+ {message.type === 'user' ? '👤 You' :
385
+ message.type === 'agent' ? '🤖 Agent' :
386
+ message.type === 'error' ? '❌ Error' : 'â„šī¸ System'}
387
+ &lt;/div&gt;
388
+ &lt;div&gt;{message.text}&lt;/div&gt;
389
+ &lt;div style={{
390
+ fontSize: '12px',
391
+ color: '#6B7280',
392
+ marginTop: '4px'
393
+ }}&gt;
394
+ {message.timestamp.toLocaleTimeString()}
395
+ &lt;/div&gt;
396
+ &lt;/div&gt;
397
+ ))
398
+ )}
399
+ &lt;/div&gt;
400
+
401
+ &lt;div style={{
402
+ display: 'flex',
403
+ gap: '20px',
404
+ marginTop: '20px',
405
+ fontSize: '14px',
406
+ color: '#6B7280'
407
+ }}&gt;
408
+ &lt;div&gt;
409
+ &lt;span style={{
410
+ display: 'inline-block',
411
+ width: '8px',
412
+ height: '8px',
413
+ borderRadius: '50%',
414
+ backgroundColor: isConnected ? '#10B981' : '#EF4444',
415
+ marginRight: '8px'
416
+ }}&gt;&lt;/span&gt;
417
+ Connection
418
+ &lt;/div&gt;
419
+ &lt;div&gt;
420
+ &lt;span style={{
421
+ display: 'inline-block',
422
+ width: '8px',
423
+ height: '8px',
424
+ borderRadius: '50%',
425
+ backgroundColor: isRecording ? '#EF4444' : '#9CA3AF',
426
+ marginRight: '8px'
427
+ }}&gt;&lt;/span&gt;
428
+ Recording
429
+ &lt;/div&gt;
430
+ &lt;div&gt;
431
+ &lt;span style={{
432
+ display: 'inline-block',
433
+ width: '8px',
434
+ height: '8px',
435
+ borderRadius: '50%',
436
+ backgroundColor: isPlaying ? '#10B981' : '#9CA3AF',
437
+ marginRight: '8px'
438
+ }}&gt;&lt;/span&gt;
439
+ Playing
440
+ &lt;/div&gt;
441
+ &lt;/div&gt;
442
+ &lt;/div&gt;
443
+ );
444
+ }
445
+
446
+ export default AdvancedVoiceChat;
447
+ </div>
448
+
449
+ <div class="note">
450
+ <strong>Note:</strong> This is a comprehensive React example showing how to integrate the VoiceSDK.
451
+ Copy this code into your React application and customize the agentId and appId values.
452
+ </div>
453
+ </div>
454
+ </body>
455
+ </html>