jjmandog commited on
Commit
80717dc
·
verified ·
1 Parent(s): 5ab2d2c

Recode ui update all - Follow Up Deployment

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +1811 -19
  3. prompts.txt +13 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Tester
3
- emoji: 🔥
4
- colorFrom: yellow
5
- colorTo: gray
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: tester
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: purple
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1811 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+
4
+
5
+ =======
6
+
7
+
8
+
9
+ <!DOCTYPE html>
10
+ <html lang="en">
11
+ =======
12
+
13
+
14
+
15
+
16
+ =======
17
+
18
+
19
+
20
+ <div>
21
+ <label class="block text-sm font-medium text-gray-700 mb-1">Memory Retention</label>
22
+ <select class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 text-sm">
23
+ <option>7 days</option>
24
+ <option>14 days</option>
25
+ <option selected>30 days</option>
26
+ <option>90 days</option>
27
+ <option>Indefinitely</option>
28
+ </select>
29
+ <p class="mt-1 text-xs text-gray-500">How long should AI remember conversation history?</p>
30
+ </div>
31
+ </div>
32
+ </div>
33
+
34
+ <div>
35
+ <label class="flex items-center space-x-3">
36
+ <input type="checkbox" checked class="rounded h-4 w-4 text-indigo-600 focus:ring-indigo-500">
37
+ <span class="text-sm font-medium text-gray-700">Daily Training Reminders</span>
38
+ </label>
39
+ </div>
40
+ =======
41
+
42
+
43
+ // Initialize on page load
44
+ document.addEventListener('DOMContentLoaded', function() {
45
+ // Close when clicking outside modals
46
+ document.querySelectorAll('.modal-overlay').forEach(modal => {
47
+ modal.addEventListener('click', (e) => {
48
+ if (e.target === modal) {
49
+ modal.classList.add('hidden');
50
+ }
51
+ });
52
+ });
53
+
54
+ // Initialize Twilio device with default settings
55
+ if (typeof Twilio !== 'undefined') {
56
+ const defaultToken = generateDefaultTwilioToken();
57
+ initializeTwilioDevice(defaultToken);
58
+ }
59
+ // Check for saved settings
60
+ const savedSettings = localStorage.getItem('aiCallSettings');
61
+ if (savedSettings) {
62
+ const config = JSON.parse(savedSettings);
63
+
64
+ // Update phone number displays
65
+ document.querySelectorAll('.phone-number-display').forEach(el => {
66
+ el.textContent = formatPhoneNumber(config.phoneNumber);
67
+ });
68
+
69
+ // Update stats with saved data
70
+ if (config.callStats) {
71
+ document.getElementById('callStatsCount').textContent = config.callStats;
72
+ }
73
+ if (config.textStats) {
74
+ document.getElementById('textStatsCount').textContent = config.textStats;
75
+ }
76
+ }
77
+
78
+ // Initialize Twilio device if token exists
79
+ const twilioSettings = localStorage.getItem('twilioSettings');
80
+ if (twilioSettings) {
81
+ const { token } = JSON.parse(twilioSettings);
82
+ initializeTwilioDevice(token);
83
+ }
84
+ });
85
+
86
+ function formatPhoneNumber(phoneNumberString) {
87
+ // Format phone number for display
88
+ const cleaned = ('' + phoneNumberString).replace(/\D/g, '');
89
+ const match = cleaned.match(/^(1|)?(\d{3})(\d{3})(\d{4})$/);
90
+ if (match) {
91
+ return ['(', match[2], ') ', match[3], '-', match[4]].join('');
92
+ }
93
+ return phoneNumberString;
94
+ }
95
+ =======
96
+
97
+
98
+ =======
99
+
100
+
101
+
102
+ <div>
103
+ <label class="block text-sm font-medium text-gray-700 mb-1">Memory Retention</label>
104
+ <select class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 text-sm">
105
+ <option>7 days</option>
106
+ <option>14 days</option>
107
+ <option selected>30 days</option>
108
+ <option>90 days</option>
109
+ <option>Indefinitely</option>
110
+ </select>
111
+ <p class="mt-1 text-xs text-gray-500">How long should AI remember conversation history?</p>
112
+ </div>
113
+ </div>
114
+ </div>
115
+
116
+ <div>
117
+ <label class="flex items-center space-x-3">
118
+ <input type="checkbox" checked class="rounded h-4 w-4 text-indigo-600 focus:ring-indigo-500">
119
+ <span class="text-sm font-medium text-gray-700">Daily Training Reminders</span>
120
+ </label>
121
+ </div>
122
+ =======
123
+
124
+
125
+
126
+ <!DOCTYPE html>
127
+ <html lang="en">
128
+ <head>
129
+ <meta charset="UTF-8">
130
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
131
+ <title>AI Call Manager</title>
132
+ <script src="https://cdn.tailwindcss.com/3.4.0"></script>
133
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
134
+ <script src="https://sdk.vercel.app/external_api.js"></script>
135
+ <script src="https://sdk.twilio.com/js/client/releases/1.14.1/twilio.min.js"></script>
136
+ <script src="https://cdn.apple-mapkit.com/mk/5.x/mapkit.js"></script>
137
+ <!-- Added Pusher for real-time chat -->
138
+ <script src="https://js.pusher.com/8.2.0/pusher.min.js"></script>
139
+ <style>
140
+ @keyframes pulse-ring {
141
+ 0% { transform: scale(0.33); }
142
+ 80%, 100% { opacity: 0; }
143
+ }
144
+ @keyframes pulse-dot {
145
+ 0% { transform: scale(0.8); }
146
+ 50% { transform: scale(1); }
147
+ 100% { transform: scale(0.8); }
148
+ }
149
+ /* Custom scrollbar */
150
+ .custom-scrollbar::-webkit-scrollbar {
151
+ width: 6px;
152
+ }
153
+ .custom-scrollbar::-webkit-scrollbar-track {
154
+ background: rgba(156, 163, 175, 0.1);
155
+ }
156
+ .custom-scrollbar::-webkit-scrollbar-thumb {
157
+ background: rgba(99, 102, 241, 0.5);
158
+ border-radius: 3px;
159
+ }
160
+ /* Call animation */
161
+ .call-animation {
162
+ position: relative;
163
+ width: 50px;
164
+ height: 50px;
165
+ }
166
+ .call-animation:before {
167
+ content: '';
168
+ position: absolute;
169
+ top: 0;
170
+ left: 0;
171
+ width: 100%;
172
+ height: 100%;
173
+ background-color: rgba(16, 185, 129, 0.5);
174
+ border-radius: 50%;
175
+ animation: pulse-ring 1.5s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
176
+ }
177
+ .call-animation:after {
178
+ content: '';
179
+ position: absolute;
180
+ top: 0;
181
+ left: 0;
182
+ width: 100%;
183
+ height: 100%;
184
+ background-color: #10B981;
185
+ border-radius: 50%;
186
+ transform: scale(0.8);
187
+ animation: pulse-dot 1.5s cubic-bezier(0.455, 0.03, 0.515, 0.955) -0.4s infinite;
188
+ }
189
+ </style>
190
+ </head>
191
+ <body class="bg-gray-100 min-h-screen font-sans">
192
+ <div class="container mx-auto px-4 py-6 max-w-md">
193
+ <!-- Header -->
194
+ <header class="flex justify-between items-center mb-6">
195
+ <h1 class="text-2xl font-bold bg-gradient-to-r from-blue-600 to-violet-600 bg-clip-text text-transparent">Call AI Pro</h1>
196
+ <div class="flex items-center space-x-3">
197
+ <div class="h-2 w-2 rounded-full bg-green-500 animate-pulse"></div>
198
+ <span class="text-sm font-medium text-gray-500">Active</span>
199
+ </div>
200
+ </header>
201
+
202
+ <!-- Main Dashboard -->
203
+ <div class="bg-white rounded-xl shadow-lg overflow-hidden mb-4 border border-gray-100">
204
+ <div class="p-5">
205
+ <div class="flex items-center mb-5">
206
+ <div class="relative mr-4">
207
+ <div class="call-animation"></div>
208
+ <div class="absolute inset-0 flex items-center justify-center">
209
+ <i class="fas fa-phone text-white text-sm"></i>
210
+ </div>
211
+ </div>
212
+ <div>
213
+ <h2 class="text-lg font-semibold text-gray-800">Call Management</h2>
214
+ <p class="text-xs text-gray-500 tracking-wider">ACTIVE NUMBER: <span class="font-medium phone-number-display">(562) 228-9429</span></p>
215
+ </div>
216
+ </div>
217
+
218
+ <!-- Call Management Section -->
219
+ <div class="space-y-4">
220
+ <div>
221
+ <label class="block text-sm font-medium text-gray-700 mb-1">Answer Calls After</label>
222
+ <select id="callDelay" class="w-full py-2.5 px-3 border border-gray-200 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-gray-50 text-sm">
223
+ <option value="15">15 seconds</option>
224
+ <option value="30" selected>30 seconds</option>
225
+ <option value="45">45 seconds</option>
226
+ <option value="60">1 minute</option>
227
+ </select>
228
+ </div>
229
+
230
+ <div>
231
+ <label class="flex items-center space-x-3">
232
+ <input type="checkbox" id="enableCallAI" class="rounded h-5 w-5 text-indigo-600 focus:ring-indigo-500" checked>
233
+ <span class="text-sm font-medium text-gray-700">Enable Call AI Assistant</span>
234
+ </label>
235
+ <p class="mt-1 text-xs text-gray-500">AI will answer calls when you're unavailable</p>
236
+ </div>
237
+
238
+ <div id="callSettings" class="pl-8">
239
+ <div class="mt-3">
240
+ <label class="block text-sm font-medium text-gray-700 mb-1">AI Voice</label>
241
+ <select class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
242
+ <option>American Female (Emma)</option>
243
+ <option>American Male (Brian)</option>
244
+ <option>British Female (Amy)</option>
245
+ </select>
246
+ </div>
247
+
248
+ <div class="mt-3">
249
+ <label class="block text-sm font-medium text-gray-700 mb-1">Default Message</label>
250
+ <textarea id="callGreeting" rows="2" class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="Hello, I'm unable to take your call right now. Please leave a message or send a text and I'll get back to you soon."></textarea>
251
+ </div>
252
+ </div>
253
+ </div>
254
+ </div>
255
+ <div class="bg-gray-50 px-5 py-3 border-t border-gray-100 flex justify-between text-xs">
256
+ <div class="text-gray-500">
257
+ <span class="font-medium text-gray-700">128</span> calls managed
258
+ </div>
259
+ <div class="text-gray-500">
260
+ <span class="font-medium text-gray-700">89%</span> accuracy
261
+ </div>
262
+ <div class="text-gray-500">
263
+ <span class="font-medium text-gray-700">24h</span> uptime
264
+ </div>
265
+ </div>
266
+ </div>
267
+
268
+ <!-- Make a Call Section -->
269
+ <div class="bg-white rounded-xl shadow-lg overflow-hidden mb-6">
270
+ <div class="p-6">
271
+ <div class="flex items-center justify-between mb-5 pb-3 border-b border-gray-100">
272
+ <div class="flex items-center">
273
+ <div class="w-10 h-10 flex items-center justify-center bg-blue-50 rounded-lg mr-3">
274
+ <i class="fas fa-phone text-blue-500 text-lg"></i>
275
+ </div>
276
+ <div>
277
+ <h2 class="text-lg font-semibold text-gray-800">Make a Call</h2>
278
+ <p class="text-xs text-gray-500">Train AI with interactive calls</p>
279
+ </div>
280
+ </div>
281
+ <div class="text-xs bg-blue-50 text-blue-600 px-2 py-1 rounded">
282
+ <i class="fas fa-bolt mr-1"></i> Quick Dial
283
+ </div>
284
+ </div>
285
+
286
+ <div class="space-y-4">
287
+ <div>
288
+ <label class="block text-sm font-medium text-gray-700 mb-1">Phone Number to Call</label>
289
+ <input type="tel" id="callNumber" class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="e.g. (562) 228-9429" value="15622289429">
290
+ </div>
291
+
292
+ <div>
293
+ <label class="block text-sm font-medium text-gray-700 mb-1">Call Purpose</label>
294
+ <select id="callPurpose" class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
295
+ <option value="training">AI Training Session</option>
296
+ <option value="outgoing">Regular Outgoing Call</option>
297
+ </select>
298
+ </div>
299
+
300
+ <div id="trainingOptions" class="pl-4 space-y-3 hidden">
301
+ <label class="flex items-center space-x-3">
302
+ <input type="checkbox" id="enableCallTraining" class="rounded h-4 w-4 text-blue-600 focus:ring-blue-500" checked>
303
+ <span class="text-sm font-medium text-gray-700">Enable Interactive Training</span>
304
+ </label>
305
+ <div>
306
+ <label class="block text-sm font-medium text-gray-700 mb-1">Training Mode</label>
307
+ <select id="callTrainingMode" class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm">
308
+ <option value="qa">Q&A Training</option>
309
+ <option value="conversation">Conversation Practice</option>
310
+ <option value="scenario">Scenario Simulation</option>
311
+ </select>
312
+ </div>
313
+ </div>
314
+
315
+ <button id="startCallBtn" class="w-full py-3 px-4 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition flex items-center justify-center space-x-2">
316
+ <i class="fas fa-phone"></i>
317
+ <span>Start Call</span>
318
+ </button>
319
+ </div>
320
+ </div>
321
+ </div>
322
+
323
+ <!-- Text AI Section -->
324
+ <div class="bg-white rounded-xl shadow-lg overflow-hidden mb-6">
325
+ <div class="p-6">
326
+ <div class="flex items-center justify-between mb-5 pb-3 border-b border-gray-100">
327
+ <div class="flex items-center">
328
+ <div class="w-10 h-10 flex items-center justify-center bg-purple-50 rounded-lg mr-3">
329
+ <i class="fas fa-comment-alt text-purple-500 text-lg"></i>
330
+ </div>
331
+ <div>
332
+ <h2 class="text-lg font-semibold text-gray-800">Text AI Assistant</h2>
333
+ <p class="text-xs text-gray-500">Smart responses & automated replies</p>
334
+ </div>
335
+ </div>
336
+ <div class="flex space-x-1">
337
+ <div class="w-2 h-2 rounded-full bg-purple-400"></div>
338
+ <div class="w-2 h-2 rounded-full bg-purple-300"></div>
339
+ <div class="w-2 h-2 rounded-full bg-purple-200"></div>
340
+ </div>
341
+ </div>
342
+
343
+ <div class="space-y-4">
344
+ <div>
345
+ <label class="flex items-center space-x-3">
346
+ <input type="checkbox" id="enableTextAI" class="rounded h-5 w-5 text-purple-600 focus:ring-purple-500" checked>
347
+ <span class="text-sm font-medium text-gray-700">Enable Text AI Assistant</span>
348
+ </label>
349
+ <p class="mt-1 text-xs text-gray-500">AI will respond to unanswered texts automatically</p>
350
+ </div>
351
+
352
+ <div id="textSettings" class="pl-8 space-y-4">
353
+ <div>
354
+ <label class="block text-sm font-medium text-gray-700 mb-1">Response Style</label>
355
+ <select id="responseStyle" class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500">
356
+ <option value="professional">Professional</option>
357
+ <option value="friendly" selected>Friendly</option>
358
+ <option value="concise">Concise</option>
359
+ </select>
360
+ </div>
361
+
362
+ <div>
363
+ <label class="block text-sm font-medium text-gray-700 mb-1">Auto-response Delay</label>
364
+ <select id="textDelay" class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500">
365
+ <option value="1">1 hour</option>
366
+ <option value="2" selected>2 hours</option>
367
+ <option value="4">4 hours</option>
368
+ <option value="6">6 hours</option>
369
+ <option value="12">12 hours</option>
370
+ </select>
371
+ </div>
372
+
373
+ <div class="pt-2">
374
+ <button id="trainAIbtn" class="w-full py-2 px-4 bg-purple-600 hover:bg-purple-700 text-white rounded-lg transition flex items-center justify-center space-x-2">
375
+ <i class="fas fa-brain"></i>
376
+ <span>Train Text AI</span>
377
+ </button>
378
+ </div>
379
+ </div>
380
+ </div>
381
+ </div>
382
+ </div>
383
+
384
+ <!-- Stats Section -->
385
+ <div class="bg-white rounded-xl shadow-lg overflow-hidden mb-6">
386
+ <div class="p-6">
387
+ <h2 class="text-lg font-semibold text-gray-800 mb-4">Usage Statistics</h2>
388
+ <div class="grid grid-cols-2 gap-4">
389
+ <div class="bg-indigo-50 p-3 rounded-lg">
390
+ <p class="text-xs text-indigo-600 font-medium">Calls Managed</p>
391
+ <p class="text-2xl font-bold text-indigo-700" id="callStatsCount">128</p>
392
+ </div>
393
+ <div class="bg-purple-50 p-3 rounded-lg">
394
+ <p class="text-xs text-purple-600 font-medium">Texts Responded</p>
395
+ <p class="text-2xl font-bold text-purple-700" id="textStatsCount">342</p>
396
+ </div>
397
+ <div class="bg-green-50 p-3 rounded-lg">
398
+ <p class="text-xs text-green-600 font-medium">AI Confidence</p>
399
+ <p class="text-2xl font-bold text-green-700">89%</p>
400
+ </div>
401
+ <div class="bg-yellow-50 p-3 rounded-lg">
402
+ <p class="text-xs text-yellow-600 font-medium">Training Cycles</p>
403
+ <p class="text-2xl font-bold text-yellow-700">24</p>
404
+ </div>
405
+ </div>
406
+ </div>
407
+ </div>
408
+
409
+ <!-- Call Log Preview -->
410
+ <div class="bg-white rounded-xl shadow-lg overflow-hidden">
411
+ <div class="p-6">
412
+ <div class="flex justify-between items-center mb-4">
413
+ <h2 class="text-lg font-semibold text-gray-800">Recent Activity</h2>
414
+ <button class="text-xs text-indigo-600 hover:text-indigo-800">View All</button>
415
+ </div>
416
+ <div class="space-y-3 max-h-60 overflow-y-auto custom-scrollbar">
417
+ <div class="flex items-start py-2 border-b border-gray-100">
418
+ <div class="flex-shrink-0 h-10 w-10 rounded-full bg-red-100 flex items-center justify-center mr-3">
419
+ <i class="fas fa-phone-alt text-red-500"></i>
420
+ </div>
421
+ <div class="flex-1">
422
+ <p class="text-sm font-medium text-gray-800">Missed Call</p>
423
+ <p class="text-xs text-gray-500">From: (562) 555-0134</p>
424
+ <p class="text-xs text-gray-500">14 min ago - AI answered after 30s</p>
425
+ </div>
426
+ </div>
427
+ <div class="flex items-start py-2 border-b border-gray-100">
428
+ <div class="flex-shrink-0 h-10 w-10 rounded-full bg-green-100 flex items-center justify-center mr-3">
429
+ <i class="fas fa-sms text-green-500"></i>
430
+ </div>
431
+ <div class="flex-1">
432
+ <p class="text-sm font-medium text-gray-800">Text Response</p>
433
+ <p class="text-xs text-gray-500">To: (562) 555-0198</p>
434
+ <p class="text-xs text-gray-500">1 hour ago - AI confidence: 92%</p>
435
+ </div>
436
+ </div>
437
+ <div class="flex items-start py-2 border-b border-gray-100">
438
+ <div class="flex-shrink-0 h-10 w-10 rounded-full bg-blue-100 flex items-center justify-center mr-3">
439
+ <i class="fas fa-phone-alt text-blue-500"></i>
440
+ </div>
441
+ <div class="flex-1">
442
+ <p class="text-sm font-medium text-gray-800">AI Call</p>
443
+ <p class="text-xs text-gray-500">With: (562) 555-0163 (2m 43s)</p>
444
+ <p class="text-xs text-gray-500">3 hours ago - Scheduled follow-up</p>
445
+ </div>
446
+ </div>
447
+ </div>
448
+ </div>
449
+
450
+ <!-- Container for Jitsi meetings (hidden by default) -->
451
+ <div id="jitsi-container" style="display: none;"></div>
452
+
453
+ <!-- Training Modal -->
454
+ <div id="trainingModal" class="modal-overlay fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 hidden">
455
+ <div class="bg-white rounded-xl shadow-xl w-full max-w-md max-h-screen overflow-y-auto">
456
+ <div class="p-6">
457
+ <div class="flex justify-between items-center mb-4">
458
+ <h3 class="text-lg font-semibold text-gray-900">Train Your Text AI</h3>
459
+ <button id="closeTraining" class="text-gray-500 hover:text-gray-700">
460
+ <i class="fas fa-times"></i>
461
+ </button>
462
+ </div>
463
+
464
+ <div class="space-y-4">
465
+ <div class="p-4 bg-gray-50 rounded-lg">
466
+ <p class="text-sm text-gray-700 mb-2">AI Knowledge Level: <span class="font-medium">Intermediate</span></p>
467
+ <div class="w-full bg-gray-200 rounded-full h-2.5">
468
+ <div class="bg-purple-600 h-2.5 rounded-full" style="width: 65%"></div>
469
+ </div>
470
+ </div>
471
+
472
+ <div>
473
+ <p class="text-sm font-medium text-gray-700 mb-2">Training Mode</p>
474
+ <div class="grid grid-cols-2 gap-2">
475
+ <button class="trainingModeBtn py-2 px-3 border border-gray-300 rounded-lg text-sm font-medium bg-white hover:bg-gray-50" data-mode="qa">Q&A Training</button>
476
+ <button class="trainingModeBtn py-2 px-3 border border-gray-300 rounded-lg text-sm font-medium bg-white hover:bg-gray-50" data-mode="examples">Teach with Examples</button>
477
+ <button class="trainingModeBtn py-2 px-3 border border-gray-300 rounded-lg text-sm font-medium bg-white hover:bg-gray-50" data-mode="keywords">Keyword Responses</button>
478
+ <button class="trainingModeBtn py-2 px-3 border border-gray-300 rounded-lg text-sm font-medium bg-white hover:bg-gray-50" data-mode="prefs">Style Preferences</button>
479
+ </div>
480
+ </div>
481
+
482
+ <!-- Q&A Training Section -->
483
+ <div id="qaTraining" class="trainingSection hidden">
484
+ <div class="space-y-4">
485
+ <div>
486
+ <label class="block text-sm font-medium text-gray-700 mb-1">Question to Teach</label>
487
+ <input type="text" class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 text-sm" placeholder="E.g. What are your business hours?">
488
+ </div>
489
+ <div>
490
+ <label class="block text-sm font-medium text-gray-700 mb-1">Preferred Response</label>
491
+ <textarea class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 text-sm" rows="3" placeholder="Our business hours are Monday to Friday, 9am to 5pm PST."></textarea>
492
+ </div>
493
+ <button class="w-full py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-lg text-sm">
494
+ Add to AI Knowledge
495
+ </button>
496
+ </div>
497
+ </div>
498
+
499
+ <!-- Examples Training Section -->
500
+ <div id="examplesTraining" class="trainingSection hidden">
501
+ <div class="space-y-4">
502
+ <div>
503
+ <label class="block text-sm font-medium text-gray-700 mb-1">Example Conversation</label>
504
+ <textarea class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 text-sm" rows="5" placeholder="Client: When can I expect my order to arrive?
505
+ You: Your order will ship within 24 hours and typically arrives in 2-3 business days. We'll send tracking information once it's on the way."></textarea>
506
+ </div>
507
+ <button class="w-full py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-lg text-sm">
508
+ Analyze for Patterns
509
+ </button>
510
+ </div>
511
+ </div>
512
+
513
+ <!-- Keywords Training Section -->
514
+ <div id="keywordsTraining" class="trainingSection hidden">
515
+ <div class="space-y-4">
516
+ <div>
517
+ <label class="block text-sm font-medium text-gray-700 mb-1">Trigger Word/Phrase</label>
518
+ <input type="text" class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 text-sm" placeholder="E.g. refund, return policy">
519
+ </div>
520
+ <div>
521
+ <label class="block text-sm font-medium text-gray-700 mb-1">Response for This Keyword</label>
522
+ <textarea class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 text-sm" rows="3" placeholder="Our return policy allows for returns within 30 days of purchase..."></textarea>
523
+ </div>
524
+ <button class="w-full py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-lg text-sm">
525
+ Add Keyword Response
526
+ </button>
527
+ </div>
528
+ </div>
529
+
530
+ <!-- Preferences Training Section -->
531
+ <div id="prefsTraining" class="trainingSection hidden">
532
+ <div class="space-y-4">
533
+ <div>
534
+ <label class="block text-sm font-medium text-gray-700 mb-1">Communication Style</label>
535
+ <select class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 text-sm">
536
+ <option>Professional</option>
537
+ <option selected>Friendly</option>
538
+ <option>Concise</option>
539
+ <option>Detailed</option>
540
+ </select>
541
+ </div>
542
+ <div>
543
+ <label class="block text-sm font-medium text-gray-700 mb-1">Common Phrases You Use</label>
544
+ <textarea class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 text-sm" rows="3" placeholder="E.g. Thanks for reaching out!, Happy to help!, Let me check that for you..."></textarea>
545
+ </div>
546
+ <button class="w-full py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-lg text-sm">
547
+ Update Preferences
548
+ </button>
549
+ </div>
550
+ </div>
551
+
552
+ <div class="pt-4 border-t border-gray-200">
553
+ <h4 class="text-sm font-medium text-gray-900 mb-2">AI Test Area</h4>
554
+ <div class="mb-2">
555
+ <input type="text" class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 text-sm" placeholder="Test message for AI to respond to" id="testMessage">
556
+ </div>
557
+ <button onclick="testAIResponse()" class="w-full py-2 bg-gray-200 hover:bg-gray-300 rounded-lg text-sm mb-4">
558
+ Test AI Response
559
+ </button>
560
+ <div id="aiResponse" class="hidden bg-gray-50 p-3 rounded-lg">
561
+ <p class="text-sm text-gray-800">This is where the AI's response would appear based on its current training.</p>
562
+ </div>
563
+ </div>
564
+ </div>
565
+ </div>
566
+ </div>
567
+ </div>
568
+
569
+ <!-- Settings Modal -->
570
+ <div id="settingsModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 hidden">
571
+ <div class="bg-white rounded-xl shadow-xl w-full max-w-md max-h-screen overflow-y-auto">
572
+ <div class="p-6">
573
+ <div class="flex justify-between items-center mb-4">
574
+ <h3 class="text-lg font-semibold text-gray-900">Settings</h3>
575
+ <button id="closeSettings" class="text-gray-500 hover:text-gray-700">
576
+ <i class="fas fa-times"></i>
577
+ </button>
578
+ </div>
579
+
580
+ <div class="space-y-4">
581
+ =======
582
+
583
+ <div>
584
+ <label class="block text-sm font-medium text-gray-700 mb-1">Memory Retention</label>
585
+ <select class="w-full py-2 px-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 text-sm">
586
+ <option>7 days</option>
587
+ <option>14 days</option>
588
+ <option selected>30 days</option>
589
+ <option>90 days</option>
590
+ <option>Indefinitely</option>
591
+ </select>
592
+ <p class="mt-1 text-xs text-gray-500">How long should AI remember conversation history?</p>
593
+ </div>
594
+
595
+ <div>
596
+ <label class="flex items-center space-x-3">
597
+ <input type="checkbox" checked class="rounded h-4 w-4 text-indigo-600 focus:ring-indigo-500">
598
+ <span class="text-sm font-medium text-gray-700">Daily Training Reminders</span>
599
+ </label>
600
+ </div>
601
+
602
+ <div class="pt-4 border-t border-gray-200">
603
+ <h4 class="text-sm font-medium text-gray-900 mb-2">AI Advanced Settings</h4>
604
+ <button id="showTwilioBtn" class="w-full py-2 mb-4 text-sm bg-gray-200 hover:bg-gray-300 rounded-lg">Show Twilio Credentials</button>
605
+
606
+ <div id="twilioCredentials" class="hidden bg-gray-50 p-3 rounded-lg space-y-2">
607
+ <div>
608
+ <label class="block text-xs font-medium text-gray-500 mb-1">Twilio Account SID</label>
609
+ <div class="flex">
610
+ <input type="text" id="twilioSid" class="flex-1 text-xs py-1 px-2 bg-white border border-gray-300 rounded-l" placeholder="ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">
611
+ <button class="copyBtn px-2 text-xs bg-gray-100 border border-l-0 border-gray-300 rounded-r text-blue-600 hover:bg-gray-200" data-target="twilioSid">
612
+ <i class="fas fa-copy"></i>
613
+ </button>
614
+ </div>
615
+ </div>
616
+ <div>
617
+ <label class="block text-xs font-medium text-gray-500 mb-1">Twilio Auth Token</label>
618
+ <div class="flex">
619
+ <div class="relative flex-1">
620
+ <input type="password" id="twilioToken" class="w-full text-xs py-1 px-2 bg-white border border-gray-300 rounded-l" placeholder="Your auth token">
621
+ <button class="togglePassword absolute right-1 top-1 text-gray-500 hover:text-gray-700 text-xs">
622
+ <i class="far fa-eye"></i>
623
+ </button>
624
+ </div>
625
+ <button class="copyBtn px-2 text-xs bg-gray-100 border border-l-0 border-gray-300 rounded-r text-blue-600 hover:bg-gray-200" data-target="twilioToken">
626
+ <i class="fas fa-copy"></i>
627
+ </button>
628
+ </div>
629
+ </div>
630
+ <div>
631
+ <label class="block text-xs font-medium text-gray-500 mb-1">Application SID</label>
632
+ <input type="text" id="twilioAppSid" class="w-full text-xs py-1 px-2 bg-white border border-gray-300 rounded" placeholder="APXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">
633
+ </div>
634
+ <div class="pt-2">
635
+ <button id="saveTwilioBtn" class="w-full py-1 text-xs bg-blue-600 hover:bg-blue-700 text-white rounded">
636
+ Save & Generate Token
637
+ </button>
638
+ <p class="text-xs text-gray-500 mt-2">Token expires in: <span id="tokenExpiry">Not generated</span></p>
639
+ <p class="text-xs text-red-500 mt-1">Keep credentials secure!</p>
640
+ </div>
641
+ </div>
642
+ <div class="mb-2">
643
+ <label class="block text-xs font-medium text-gray-700 mb-1">Creativity Level</label>
644
+ <input type="range" min="0" max="10" value="7" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
645
+ <div class="flex justify-between text-xs text-gray-500 px-1">
646
+ <span>Precise</span>
647
+ <span>Balanced</span>
648
+ <span>Creative</span>
649
+ </div>
650
+ </div>
651
+ </div>
652
+
653
+ <div class="flex space-x-3 pt-4">
654
+ <button class="flex-1 py-2 bg-gray-200 hover:bg-gray-300 rounded-lg text-sm">
655
+ Reset Training
656
+ </button>
657
+ <button class="flex-1 py-2 bg-indigo-600 hover:bg-indigo-700 text-white rounded-lg text-sm">
658
+ Save Settings
659
+ </button>
660
+ </div>
661
+ </div>
662
+ </div>
663
+ </div>
664
+ </div>
665
+
666
+ <script>
667
+ // Twilio Client Setup
668
+ const twilioDevice = new Twilio.Device();
669
+ let activeConnection = null;
670
+ let currentCallSid = null;
671
+
672
+ // Initialize Twilio device
673
+ function initializeTwilioDevice(token) {
674
+ twilioDevice.setup(token, {
675
+ closeProtection: true,
676
+ logLevel: 1,
677
+ codecPreferences: ['opus', 'pcmu']
678
+ });
679
+
680
+ twilioDevice.on('ready', () => {
681
+ updateConnectionStatus('Connected', 'green-500');
682
+ });
683
+
684
+ twilioDevice.on('error', (error) => {
685
+ updateConnectionStatus(`Error: ${error.message}`, 'red-500');
686
+ });
687
+
688
+ twilioDevice.on('disconnect', () => {
689
+ updateConnectionStatus('Disconnected', 'red-500');
690
+ });
691
+
692
+ // Incoming call handling
693
+ twilioDevice.on('incoming', (connection) => {
694
+ incomingCall(connection);
695
+ });
696
+ }
697
+
698
+ function updateConnectionStatus(text, color) {
699
+ const statusEl = document.getElementById('twilioStatus');
700
+ const iconEl = document.getElementById('connectionStatusIcon');
701
+ const textEl = document.getElementById('connectionStatusText');
702
+
703
+ statusEl.classList.remove('hidden');
704
+ textEl.textContent = text;
705
+ iconEl.className = `fas fa-circle text-${color} mr-2`;
706
+ }
707
+
708
+ function incomingCall(connection) {
709
+ activeConnection = connection;
710
+ currentCallSid = connection.parameters.CallSid;
711
+
712
+ // Show incoming call UI
713
+ const callModal = document.createElement('div');
714
+ callModal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50';
715
+ callModal.innerHTML = `
716
+ <div class="bg-white rounded-xl shadow-lg w-full max-w-sm">
717
+ <div class="p-6">
718
+ <div class="text-center mb-4">
719
+ <div class="call-animation mx-auto mb-4"></div>
720
+ <h3 class="text-lg font-medium text-gray-900">Incoming Call</h3>
721
+ <p class="text-sm text-gray-500">From: ${connection.parameters.From}</p>
722
+ </div>
723
+
724
+ <div class="grid grid-cols-2 gap-2">
725
+ <button id="answerBtn" class="py-3 bg-green-500 hover:bg-green-600 text-white rounded-lg">
726
+ <i class="fas fa-phone"></i> Answer
727
+ </button>
728
+ <button id="declineBtn" class="py-3 bg-red-500 hover:bg-red-600 text-white rounded-lg">
729
+ <i class="fas fa-phone-slash"></i> Decline
730
+ </button>
731
+ </div>
732
+ </div>
733
+ </div>
734
+ `;
735
+
736
+ document.body.appendChild(callModal);
737
+
738
+ // Set up button handlers
739
+ document.getElementById('answerBtn').addEventListener('click', () => {
740
+ connection.accept();
741
+ setupActiveCallUI(connection);
742
+ document.body.removeChild(callModal);
743
+ });
744
+
745
+ document.getElementById('declineBtn').addEventListener('click', () => {
746
+ connection.reject();
747
+ document.body.removeChild(callModal);
748
+ addToCallLog('Missed call from ' + connection.parameters.From);
749
+ });
750
+ }
751
+
752
+ function setupActiveCallUI(connection) {
753
+ const callUI = document.createElement('div');
754
+ callUI.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50';
755
+ callUI.innerHTML = `
756
+ <div class="bg-white rounded-xl shadow-lg w-full max-w-sm">
757
+ <div class="p-6">
758
+ <div class="text-center mb-4">
759
+ <h3 class="text-lg font-medium text-gray-900">Ongoing Call</h3>
760
+ <p class="text-sm text-gray-500" id="callStatus">Connected</p>
761
+ <p class="text-sm text-gray-500" id="callNumber">${connection.parameters.From}</p>
762
+ </div>
763
+
764
+ <div class="grid grid-cols-3 gap-2">
765
+ <button id="muteBtn" class="py-3 bg-gray-100 hover:bg-gray-200 rounded-lg">
766
+ <i class="fas fa-microphone"></i>
767
+ </button>
768
+ <button id="holdBtn" class="py-3 bg-gray-100 hover:bg-gray-200 rounded-lg">
769
+ <i class="fas fa-pause"></i>
770
+ </button>
771
+ <button id="endBtn" class="py-3 bg-red-500 hover:bg-red-600 text-white rounded-lg">
772
+ <i class="fas fa-phone-slash"></i>
773
+ </button>
774
+ </div>
775
+ </div>
776
+ </div>
777
+ `;
778
+
779
+ document.body.appendChild(callUI);
780
+
781
+ // Set up button handlers
782
+ document.getElementById('endBtn').addEventListener('click', () => {
783
+ connection.disconnect();
784
+ document.body.removeChild(callUI);
785
+ addToCallLog('Call with ' + connection.parameters.From + ' ended');
786
+ });
787
+
788
+ document.getElementById('muteBtn').addEventListener('click', (e) => {
789
+ if (connection.isMuted()) {
790
+ connection.mute(false);
791
+ e.target.classList.remove('bg-gray-200');
792
+ } else {
793
+ connection.mute(true);
794
+ e.target.classList.add('bg-gray-200');
795
+ }
796
+ });
797
+
798
+ connection.on('disconnect', () => {
799
+ if (document.body.contains(callUI)) {
800
+ document.body.removeChild(callUI);
801
+ }
802
+ });
803
+ }
804
+
805
+ function addToCallLog(entry) {
806
+ const callLog = document.querySelector('.space-y-3.max-h-60');
807
+ const logEntry = document.createElement('div');
808
+ logEntry.className = 'flex items-start py-2 border-b border-gray-100';
809
+ logEntry.innerHTML = `
810
+ <div class="flex-shrink-0 h-10 w-10 rounded-full bg-blue-100 flex items-center justify-center mr-3">
811
+ <i class="fas fa-phone-alt text-blue-500"></i>
812
+ </div>
813
+ <div class="flex-1">
814
+ <p class="text-sm font-medium text-gray-800">${entry}</p>
815
+ <p class="text-xs text-gray-500">Just now</p>
816
+ </div>
817
+ `;
818
+
819
+ callLog.insertBefore(logEntry, callLog.firstChild);
820
+ if (callLog.children.length > 5) {
821
+ callLog.removeChild(callLog.lastChild);
822
+ }
823
+ }
824
+
825
+
826
+ // Client Setup
827
+ let jitsiClient;
828
+ let callSocket;
829
+ let trillionClient = null;
830
+
831
+ async function initializeJitsiClient() {
832
+ try {
833
+ // Initialize Jitsi Meet API client
834
+ jitsiClient = {
835
+ makeCall: async (options) => {
836
+ return new Promise((resolve) => {
837
+ console.log('Initiating Jitsi call to:', options.to);
838
+ const domain = 'meet.jit.si';
839
+ const options = {
840
+ roomName: `call-${Date.now()}`,
841
+ parentNode: document.querySelector('#jitsi-container'),
842
+ userInfo: {
843
+ displayName: 'AI Call Manager'
844
+ }
845
+ };
846
+
847
+ // Create Jitsi Meet API instance
848
+ const api = new JitsiMeetExternalAPI(domain, options);
849
+
850
+ setTimeout(() => resolve({id: `jitsi-${Date.now()}`, api}), 1000);
851
+ });
852
+ }
853
+ };
854
+
855
+ // Use a simple WebSocket connection (you would replace with your own endpoint)
856
+ callSocket = new WebSocket('wss://realtime.trillion.ventures/ws');
857
+ setTimeout(() => {
858
+ if (callSocket.onopen) callSocket.onopen();
859
+ }, 500);
860
+ callSocket.onopen = () => {
861
+ console.log('Connected to Trillion real-time service');
862
+ callSocket.send(JSON.stringify({
863
+ type: 'authenticate',
864
+ token: authToken
865
+ }));
866
+ };
867
+ callSocket.onmessage = handleSocketMessage;
868
+ callSocket.onclose = () => console.log('Disconnected from real-time service');
869
+
870
+ return true;
871
+ } catch (error) {
872
+ console.error("Failed to initialize Trillion client:", error);
873
+ return false;
874
+ }
875
+ }
876
+
877
+ function handleSocketMessage(event) {
878
+ const data = JSON.parse(event.data);
879
+ switch(data.type) {
880
+ case 'call_update':
881
+ updateCallUI(data.status, data.transcript);
882
+ break;
883
+ case 'message':
884
+ console.log("New message:", data.content);
885
+ break;
886
+ case 'call_ended':
887
+ endCallUI(data.callId);
888
+ break;
889
+ }
890
+ }
891
+
892
+ async function sendSMS(to, message) {
893
+ try {
894
+ const response = await fetch('/api/send-sms', {
895
+ method: 'POST',
896
+ headers: {
897
+ 'Content-Type': 'application/json',
898
+ 'Authorization': `Bearer ${localStorage.getItem('authToken')}`
899
+ },
900
+ body: JSON.stringify({ to, message })
901
+ });
902
+
903
+ if (!response.ok) throw new Error('Failed to send SMS');
904
+ return await response.json();
905
+ } catch (error) {
906
+ console.error('SMS send error:', error);
907
+ throw error;
908
+ }
909
+ }
910
+
911
+ // Save call stats when calls are made/ended
912
+ function updateCallStats() {
913
+ const callStats = parseInt(localStorage.getItem('callStats')) || 128;
914
+ localStorage.setItem('callStats', callStats + 1);
915
+ document.querySelector('#callStatsCount').textContent = callStats + 1;
916
+ }
917
+
918
+ // AI Response Generation
919
+ async function generateAIResponse(message, context = {}) {
920
+ try {
921
+ const response = await fetch('/api/generate-ai-response', {
922
+ method: 'POST',
923
+ headers: {
924
+ 'Content-Type': 'application/json',
925
+ 'Authorization': `Bearer ${localStorage.getItem('authToken')}`
926
+ },
927
+ body: JSON.stringify({
928
+ message,
929
+ style: document.getElementById('responseStyle').value,
930
+ context
931
+ })
932
+ });
933
+
934
+ if (!response.ok) throw new Error('AI response failed');
935
+ return await response.json();
936
+ } catch (error) {
937
+ console.error('AI error:', error);
938
+ return { response: "I'm having trouble generating a response right now. Please try again later." };
939
+ }
940
+ }
941
+
942
+ // Enhanced Twilio Settings Management
943
+ let twilioToken = null;
944
+ let tokenExpiry = null;
945
+
946
+ document.getElementById('showTwilioBtn').addEventListener('click', function() {
947
+ const credsDiv = document.getElementById('twilioCredentials');
948
+ credsDiv.classList.toggle('hidden');
949
+ this.textContent = credsDiv.classList.contains('hidden') ?
950
+ 'Show Twilio Credentials' : 'Hide Twilio Credentials';
951
+
952
+ // Load saved settings if available
953
+ const savedSettings = localStorage.getItem('twilioSettings');
954
+ if (savedSettings) {
955
+ const settings = JSON.parse(savedSettings);
956
+ document.getElementById('twilioSid').value = settings.accountSid || '';
957
+ document.getElementById('twilioToken').value = settings.authToken || '';
958
+ document.getElementById('twilioAppSid').value = settings.appSid || '';
959
+ if (settings.token && settings.expiry) {
960
+ updateTokenDisplay(settings.token, settings.expiry);
961
+ }
962
+ }
963
+ });
964
+
965
+ // Save and generate token
966
+ document.getElementById('saveTwilioBtn').addEventListener('click', async function() {
967
+ const accountSid = document.getElementById('twilioSid').value.trim();
968
+ const authToken = document.getElementById('twilioToken').value.trim();
969
+ const appSid = document.getElementById('twilioAppSid').value.trim();
970
+
971
+ if (!accountSid || !authToken) {
972
+ alert('Please enter Account SID and Auth Token');
973
+ return;
974
+ }
975
+
976
+ try {
977
+ // In a real app, this would call your backend to generate the token
978
+ // For demo purposes, we'll generate a mock token
979
+ const generatedToken = await generateTwilioToken(accountSid, authToken, appSid);
980
+
981
+ // Save settings to localStorage
982
+ const settings = {
983
+ accountSid,
984
+ authToken,
985
+ appSid,
986
+ token: generatedToken.token,
987
+ expiry: generatedToken.expiry
988
+ };
989
+ localStorage.setItem('twilioSettings', JSON.stringify(settings));
990
+
991
+ // Update UI
992
+ updateTokenDisplay(generatedToken.token, generatedToken.expiry);
993
+ alert('Settings saved and token generated!');
994
+
995
+ // Restart Twilio device with new token
996
+ if (twilioDevice) {
997
+ twilioDevice.destroy();
998
+ initializeTwilioDevice(generatedToken.token);
999
+ }
1000
+ } catch (error) {
1001
+ console.error('Token generation failed:', error);
1002
+ alert('Failed to generate token: ' + error.message);
1003
+ }
1004
+ });
1005
+
1006
+ // Generate new token button
1007
+ document.getElementById('generateTokenBtn').addEventListener('click', async function() {
1008
+ const accountSid = document.getElementById('twilioSid').value.trim();
1009
+ const authToken = document.getElementById('twilioToken').value.trim();
1010
+ const appSid = document.getElementById('twilioAppSid').value.trim();
1011
+
1012
+ if (!accountSid || !authToken) {
1013
+ alert('Please enter Account SID and Auth Token first');
1014
+ return;
1015
+ }
1016
+
1017
+ try {
1018
+ const generatedToken = await generateTwilioToken(accountSid, authToken, appSid);
1019
+ updateTokenDisplay(generatedToken.token, generatedToken.expiry);
1020
+
1021
+ // Save new token
1022
+ const settings = JSON.parse(localStorage.getItem('twilioSettings') || '{}');
1023
+ settings.token = generatedToken.token;
1024
+ settings.expiry = generatedToken.expiry;
1025
+ localStorage.setItem('twilioSettings', JSON.stringify(settings));
1026
+
1027
+ // Restart Twilio device
1028
+ if (twilioDevice) {
1029
+ twilioDevice.destroy();
1030
+ initializeTwilioDevice(generatedToken.token);
1031
+ }
1032
+ } catch (error) {
1033
+ console.error('Token generation failed:', error);
1034
+ alert('Failed to generate new token: ' + error.message);
1035
+ }
1036
+ });
1037
+
1038
+ // Helper function for token display
1039
+ function updateTokenDisplay(token, expiryDate) {
1040
+ twilioToken = token;
1041
+ tokenExpiry = new Date(expiryDate);
1042
+
1043
+ // Format expiry for display
1044
+ const now = new Date();
1045
+ const diffMs = tokenExpiry - now;
1046
+ const diffDays = Math.round(diffMs / (1000 * 60 * 60 * 24));
1047
+ const diffHours = Math.round((diffMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
1048
+
1049
+ let expiryText = 'Expired';
1050
+ if (diffMs > 0) {
1051
+ expiryText = `${diffDays}d ${diffHours}h remaining`;
1052
+ }
1053
+ document.getElementById('tokenExpiry').textContent = expiryText;
1054
+ }
1055
+
1056
+ // Mock token generator (in a real app, this would call your backend)
1057
+ async function generateTwilioToken(accountSid, authToken, appSid) {
1058
+ return new Promise((resolve) => {
1059
+ // Simulate network delay
1060
+ setTimeout(() => {
1061
+ const expiryDate = new Date();
1062
+ expiryDate.setDate(expiryDate.getDate() + 1); // 1 day expiry
1063
+
1064
+ // Generate mock token
1065
+ const mockToken = `eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.${btoa(JSON.stringify({
1066
+ account_sid: accountSid,
1067
+ exp: Math.floor(expiryDate.getTime() / 1000)
1068
+ }))}.FAKETOKEN`;
1069
+
1070
+ resolve({
1071
+ token: mockToken,
1072
+ expiry: expiryDate.toISOString()
1073
+ });
1074
+ }, 1000);
1075
+ });
1076
+ }
1077
+
1078
+ // Copy buttons
1079
+ document.querySelectorAll('.copyBtn').forEach(btn => {
1080
+ btn.addEventListener('click', function() {
1081
+ const targetId = this.getAttribute('data-target');
1082
+ const input = document.getElementById(targetId);
1083
+ input.select();
1084
+ document.execCommand('copy');
1085
+
1086
+ // Visual feedback
1087
+ const originalHTML = this.innerHTML;
1088
+ this.innerHTML = '<i class="fas fa-check"></i>';
1089
+ setTimeout(() => {
1090
+ this.innerHTML = originalHTML;
1091
+ }, 2000);
1092
+ });
1093
+ });
1094
+
1095
+ // Toggle password visibility
1096
+ document.querySelectorAll('.togglePassword').forEach(btn => {
1097
+ btn.addEventListener('click', function() {
1098
+ const parent = this.closest('.relative');
1099
+ const input = parent.querySelector('input');
1100
+ if (input.type === 'password') {
1101
+ input.type = 'text';
1102
+ this.innerHTML = '<i class="far fa-eye-slash"></i>';
1103
+ } else {
1104
+ input.type = 'password';
1105
+ this.innerHTML = '<i class="far fa-eye"></i>';
1106
+ }
1107
+ });
1108
+ });
1109
+
1110
+ // Toggle settings visibility
1111
+ document.getElementById('enableCallAI').addEventListener('change', function() {
1112
+ document.getElementById('callSettings').style.display = this.checked ? 'block' : 'none';
1113
+ });
1114
+
1115
+ document.getElementById('enableTextAI').addEventListener('change', function() {
1116
+ document.getElementById('textSettings').style.display = this.checked ? 'block' : 'none';
1117
+ });
1118
+
1119
+ =======
1120
+ // Helper function to generate a default Twilio token
1121
+ function generateDefaultTwilioToken() {
1122
+ // In a real implementation, this would come from your backend
1123
+ // For demo purposes, we'll return a mock token
1124
+ return `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFJIENhbGwgTWFuYWdlciIsImlhdCI6MTUxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`;
1125
+ }
1126
+
1127
+ // Training sections
1128
+ const trainingModeBtns = document.querySelectorAll('.trainingModeBtn');
1129
+ trainingModeBtns.forEach(btn => {
1130
+ btn.addEventListener('click', () => {
1131
+ const mode = btn.dataset.mode;
1132
+ showTrainingSection(mode);
1133
+
1134
+ // Update active button style
1135
+ trainingModeBtns.forEach(b => b.classList.remove('bg-purple-100', 'border-purple-300', 'text-purple-800'));
1136
+ btn.classList.add('bg-purple-100', 'border-purple-300', 'text-purple-800');
1137
+ });
1138
+ });
1139
+
1140
+ function showTrainingSection(sectionId) {
1141
+ document.querySelectorAll('.trainingSection').forEach(section => {
1142
+ section.classList.add('hidden');
1143
+ });
1144
+ document.getElementById(sectionId + 'Training').classList.remove('hidden');
1145
+ }
1146
+
1147
+ // Call functionality with Twilio API integration
1148
+ const callPurpose = document.getElementById('callPurpose');
1149
+ const trainingOptions = document.getElementById('trainingOptions');
1150
+
1151
+ callPurpose.addEventListener('change', function() {
1152
+ trainingOptions.style.display = this.value === 'training' ? 'block' : 'none';
1153
+ });
1154
+
1155
+ document.getElementById('startCallBtn').addEventListener('click', async function() {
1156
+ const number = document.getElementById('callNumber').value.trim();
1157
+ if (!number) {
1158
+ alert('Please enter a phone number');
1159
+ return;
1160
+ }
1161
+
1162
+ const isTraining = callPurpose.value === 'training';
1163
+ const trainingMode = isTraining ? document.getElementById('callTrainingMode').value : null;
1164
+ const enableTraining = isTraining ? document.getElementById('enableCallTraining').checked : false;
1165
+
1166
+ try {
1167
+ const authToken = localStorage.getItem('authToken');
1168
+ if (!authToken) {
1169
+ alert('Please configure your authentication in Settings first');
1170
+ settingsModal.classList.remove('hidden');
1171
+ throw new Error('Authentication required');
1172
+ }
1173
+
1174
+ trillionClient = {
1175
+ calls: {
1176
+ end: async (callId) => {
1177
+ console.log('Ending call:', callId);
1178
+ return true;
1179
+ }
1180
+ }
1181
+ };
1182
+
1183
+ const callOptions = {
1184
+ to: number,
1185
+ video: false
1186
+ };
1187
+
1188
+ const call = await jitsiClient.makeCall(callOptions);
1189
+ console.log('Call initiated:', call.id);
1190
+
1191
+ // Subscribe to call updates
1192
+ callSocket.send(JSON.stringify({
1193
+ type: 'subscribe_call',
1194
+ callId: call.id
1195
+ }));
1196
+
1197
+ showCallInterface(number, isTraining, trainingMode, call.id);
1198
+
1199
+ } catch (error) {
1200
+ console.error('Call error:', error);
1201
+ alert(`Call failed: ${error.message}`);
1202
+ }
1203
+ });
1204
+
1205
+ =======
1206
+ // Load saved settings on page load
1207
+ // Advanced AI Persona Configuration
1208
+ const aiPersona = {
1209
+ name: "Jay's Mobile Wash Assistant",
1210
+ tone: "friendly/professional",
1211
+ knowledge: {
1212
+ packages: {
1213
+ basic: {
1214
+ car: 60,
1215
+ suv: 70,
1216
+ includes: "2-Step Hand Wash, Tornador Z-007 Blast, Ceramic Rim Cleaning, Interior Wipe-Down"
1217
+ },
1218
+ luxury: {
1219
+ car: 130,
1220
+ suv: 140,
1221
+ includes: "Basic Package + Ceramic Spray Wax, SiO₂ Interior Cleaner, Vinyl Restoration"
1222
+ },
1223
+ max: {
1224
+ car: 200,
1225
+ suv: 210,
1226
+ includes: "Luxury Package + Graphene Wax, Steam Sanitization, Leather Conditioning, Bio-Bomb Odor Removal"
1227
+ }
1228
+ },
1229
+ addons: [
1230
+ "Ceramic Coating (2+ years)",
1231
+ "Polish + Scratch Removal",
1232
+ "Pet Hair Removal",
1233
+ "Rim De-Iron",
1234
+ "Engine Bay Detailing",
1235
+ "Trim Restoration"
1236
+ ],
1237
+ policies: {
1238
+ surcharges: "30% for heavy dirt, 50% for biohazards, $50 for after-dark work",
1239
+ guarantee: "Daylight only, full disclosure required",
1240
+ payment: "1.75% card fee, $10 travel fee per 10 miles beyond 30"
1241
+ },
1242
+ contact: "562-228-9429 | www.jaysmobilewash.com"
1243
+ },
1244
+ capabilities: {
1245
+ research: true,
1246
+ memory: true,
1247
+ continuousLearning: true
1248
+ }
1249
+ };
1250
+
1251
+ // Initialize speech recognition
1252
+ const speechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
1253
+ const recognition = speechRecognition ? new speechRecognition() : null;
1254
+ if (recognition) {
1255
+ recognition.lang = 'en-US';
1256
+ recognition.interimResults = false;
1257
+ recognition.maxAlternatives = 1;
1258
+ }
1259
+
1260
+ document.addEventListener('DOMContentLoaded', function() {
1261
+ if (!localStorage.getItem('authToken')) {
1262
+ settingsModal.classList.remove('hidden');
1263
+ alert('Please configure your authentication settings');
1264
+ }
1265
+
1266
+ =======
1267
+ // System Test Modal
1268
+ const testModal = document.getElementById('testModal');
1269
+ const testBtn = document.getElementById('systemTestBtn');
1270
+ const closeTest = document.getElementById('closeTest');
1271
+
1272
+ testBtn.addEventListener('click', () => {
1273
+ testModal.classList.remove('hidden');
1274
+ });
1275
+
1276
+ closeTest.addEventListener('click', () => {
1277
+ testModal.classList.add('hidden');
1278
+ });
1279
+
1280
+ // Add "How to Fix" button handler
1281
+ document.getElementById('howToFixBtn').addEventListener('click', function() {
1282
+ if (!verifyNumberConfiguration()) {
1283
+ alert(`To fix call/message handling for 15622289429:
1284
+ 1. Go to Settings > Phone Integration
1285
+ 2. Enter your Twilio credentials:
1286
+ - Account SID: your_twilio_sid
1287
+ - Auth Token: your_twilio_token
1288
+ - Phone Number: 15622289429
1289
+ 3. Save & restart the app
1290
+ Or contact support at help@trillion.ventures`);
1291
+ } else {
1292
+ alert('System is properly configured for number 15622289429!');
1293
+ }
1294
+ });
1295
+
1296
+ // Rest of DOMContentLoaded...
1297
+ =======
1298
+ const savedSettings = localStorage.getItem('aiCallSettings');
1299
+ if (savedSettings) {
1300
+ const config = JSON.parse(savedSettings);
1301
+
1302
+ // Update phone number displays
1303
+ document.querySelectorAll('.phone-number-display').forEach(el => {
1304
+ el.textContent = config.twilioNum || config.phoneNum || '+1 (858) 263-4276';
1305
+ });
1306
+
1307
+ // Update stats section with saved data
1308
+ document.querySelector('#callStatsCount').textContent = localStorage.getItem('callStats') || '128';
1309
+ document.querySelector('#textStatsCount').textContent = localStorage.getItem('textStats') || '342';
1310
+ }
1311
+ });
1312
+
1313
+ // Function to update call UI with real data
1314
+ function updateCallUI(status, transcript) {
1315
+ const statusElement = document.querySelector('#callStatus');
1316
+ if (statusElement) {
1317
+ statusElement.textContent = status;
1318
+ }
1319
+
1320
+ const transcriptElement = document.querySelector('#callTranscript');
1321
+ if (transcriptElement) {
1322
+ transcriptElement.textContent = transcript;
1323
+ }
1324
+ }
1325
+
1326
+ // Call interface simulation
1327
+ function showCallInterface(number, isTraining, trainingMode) {
1328
+ const callModal = document.createElement('div');
1329
+ callModal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50';
1330
+ callModal.innerHTML = `
1331
+ <div class="bg-white rounded-xl shadow-lg w-full max-w-sm">
1332
+ <div class="p-6">
1333
+ <div class="text-center mb-4">
1334
+ <div class="call-animation mx-auto mb-4"></div>
1335
+ <h3 class="text-lg font-medium text-gray-900">Calling ${number}</h3>
1336
+ <p class="text-sm text-gray-500">${isTraining ? 'AI Training Session' : 'Outgoing Call'}</p>
1337
+ </div>
1338
+
1339
+ ${isTraining ? `
1340
+ <div class="mb-4">
1341
+ <p class="text-sm font-medium text-gray-700 mb-1">Training Mode: ${trainingMode}</p>
1342
+ <div class="bg-gray-50 p-3 rounded-lg">
1343
+ <p class="text-sm text-gray-700">AI will ask questions and learn from your responses.</p>
1344
+ </div>
1345
+ </div>` : ''}
1346
+
1347
+ <div class="mb-6">
1348
+ <p class="text-sm font-medium text-gray-700 mb-1">Current AI Knowledge Level</p>
1349
+ <div class="w-full bg-gray-200 rounded-full h-2.5 mb-1">
1350
+ <div class="bg-blue-600 h-2.5 rounded-full" style="width: 65%"></div>
1351
+ </div>
1352
+ <p class="text-xs text-gray-500">Understanding of your speech patterns: <span class="font-medium">Medium</span></p>
1353
+ </div>
1354
+
1355
+ <div class="grid grid-cols-3 gap-2">
1356
+ <button class="callBtn py-3 px-4 bg-gray-100 hover:bg-gray-200 rounded-lg flex items-center justify-center">
1357
+ <i class="fas fa-microphone text-gray-700"></i>
1358
+ </button>
1359
+ <button class="callBtn py-3 px-4 bg-green-500 hover:bg-green-600 text-white rounded-lg flex items-center justify-center">
1360
+ <i class="fas fa-check"></i>
1361
+ </button>
1362
+ <button class="callBtn py-3 px-4 bg-red-500 hover:bg-red-600 text-white rounded-lg flex items-center justify-center">
1363
+ <i class="fas fa-times"></i>
1364
+ </button>
1365
+ <button class="callBtn py-3 px-4 bg-blue-50 hover:bg-blue-100 rounded-lg flex items-center justify-center">
1366
+ <i class="fas fa-brain text-blue-700"></i>
1367
+ </button>
1368
+ <button class="callBtn py-3 px-4 bg-blue-500 hover:bg-blue-600 text-white rounded-lg flex items-center justify-center">
1369
+ <i class="fas fa-comment"></i>
1370
+ </button>
1371
+ <button class="callBtn py-3 px-4 bg-blue-50 hover:bg-blue-100 rounded-lg flex items-center justify-center">
1372
+ <i class="fas fa-history text-blue-700"></i>
1373
+ </button>
1374
+ </div>
1375
+ </div>
1376
+ </div>
1377
+ `;
1378
+
1379
+ document.body.appendChild(callModal);
1380
+
1381
+ // End call button
1382
+ const endCallBtn = callModal.querySelector('.bg-red-500');
1383
+ endCallBtn.addEventListener('click', async function() {
1384
+ try {
1385
+ await trillionClient.calls.end(callId);
1386
+ document.body.removeChild(callModal);
1387
+
1388
+ if (isTraining) {
1389
+ alert('AI training session completed. New knowledge added to memory.');
1390
+ }
1391
+ } catch (error) {
1392
+ console.error('Error ending call:', error);
1393
+ alert('Error ending call');
1394
+ }
1395
+ });
1396
+
1397
+ // In a real app, would have websockets or similar for real-time call interaction
1398
+ }
1399
+
1400
+ async function testAIResponse() {
1401
+ const testMessage = document.getElementById('testMessage').value;
1402
+ const responseBox = document.getElementById('aiResponse');
1403
+
1404
+ if (testMessage.trim() === '') {
1405
+ alert('Please enter a message to test');
1406
+ return;
1407
+ }
1408
+
1409
+ try {
1410
+ responseBox.querySelector('p').textContent = "Generating AI response...";
1411
+ responseBox.classList.remove('hidden');
1412
+
1413
+ const aiResponse = await generateAIResponse(testMessage);
1414
+ responseBox.querySelector('p').textContent = aiResponse.response;
1415
+ } catch (error) {
1416
+ responseBox.querySelector('p').textContent = "Error generating response. Please try again.";
1417
+ console.error(error);
1418
+ }
1419
+ }
1420
+
1421
+
1422
+ // Integrated webhook for all SMS sources
1423
+ app.post('/api/message-webhook', async (req, res) => {
1424
+ const { source, from, message } = req.body;
1425
+
1426
+ // Validate it's for the correct number
1427
+ if (from.includes('15622289429')) {
1428
+
1429
+ // Handle iMessage specifically
1430
+ if (source === 'imessage') {
1431
+ // Process with Apple Business Chat API
1432
+ try {
1433
+ const imResponse = await appleChatAPI.send({
1434
+ to: from,
1435
+ message: `ACK: ${message}`, // temp ack
1436
+ type: 'text'
1437
+ });
1438
+ } catch (e) {
1439
+ console.error('iMessage error:', e);
1440
+ }
1441
+ }
1442
+
1443
+ // Trigger event to frontend
1444
+ pusher.trigger(`incoming_15622289429`, 'new_message', {
1445
+ from,
1446
+ message,
1447
+ source
1448
+ });
1449
+ }
1450
+
1451
+ res.status(200).send();
1452
+ });
1453
+
1454
+ // AI Response Generation using HuggingFace
1455
+ app.post('/api/generate-response', async (req, res) => {
1456
+ const { message } = req.body;
1457
+
1458
+ try {
1459
+ const response = await hf.textGeneration({
1460
+ model: 'facebook/blenderbot-400M-distill',
1461
+ inputs: message,
1462
+ parameters: {
1463
+ max_new_tokens: 150,
1464
+ temperature: 0.7
1465
+ }
1466
+ });
1467
+
1468
+ res.json({ response: response.generated_text });
1469
+ } catch (error) {
1470
+ console.error(error);
1471
+ res.status(500).json({ error: 'Failed to generate response' });
1472
+ }
1473
+ });
1474
+
1475
+ // Test functions
1476
+ document.getElementById('testCallBtn').addEventListener('click', async function() {
1477
+ const resultEl = document.getElementById('testResultText');
1478
+ resultEl.textContent = "Initiating AI call test...";
1479
+ document.getElementById('testResults').classList.remove('hidden');
1480
+
1481
+ try {
1482
+ // Simulate calling your number
1483
+ const response = await fetch('/api/test-call', {
1484
+ method: 'POST',
1485
+ body: JSON.stringify({
1486
+ test: true,
1487
+ greeting: document.getElementById('greetingMessage').value
1488
+ })
1489
+ });
1490
+
1491
+ resultEl.textContent = "AI answered successfully! Call is active for testing.";
1492
+
1493
+ // Simulate AI learning capabilities
1494
+ setTimeout(() => {
1495
+ resultEl.textContent += "\nAI is analyzing call patterns and learning...";
1496
+ }, 2000);
1497
+
1498
+ } catch (error) {
1499
+ resultEl.textContent = `Test failed: ${error.message}`;
1500
+ }
1501
+ });
1502
+
1503
+ document.getElementById('testTextBtn').addEventListener('click', async function() {
1504
+ const resultEl = document.getElementById('testResultText');
1505
+ resultEl.textContent = "Testing AI text response system...";
1506
+ document.getElementById('testResults').classList.remove('hidden');
1507
+
1508
+ try {
1509
+ const testMsg = "Hi, how much for a full detail with ceramic coating?";
1510
+ const response = await generateAIResponse(testMsg, {
1511
+ service: "car_wash",
1512
+ context: aiPersona.knowledge
1513
+ });
1514
+
1515
+ resultEl.textContent = `AI Response: ${response.response}\n\nContext used: ${JSON.stringify(aiPersona.knowledge)}`;
1516
+ } catch (error) {
1517
+ resultEl.textContent = `Test failed: ${error.message}`;
1518
+ }
1519
+ });
1520
+
1521
+ // Enhanced AI learning capabilities
1522
+ function enhanceAILearning() {
1523
+ // Enable verbal training
1524
+ const verbalTrainingBtn = document.createElement('button');
1525
+ verbalTrainingBtn.className = 'w-full py-2 px-4 bg-green-600 hover:bg-green-700 text-white rounded-lg my-2';
1526
+ verbalTrainingBtn.innerHTML = '<i class="fas fa-microphone mr-2"></i> Verbal Training Session';
1527
+ verbalTrainingBtn.onclick = startVerbalTraining;
1528
+ document.querySelector('#trainingModal .space-y-4').appendChild(verbalTrainingBtn);
1529
+
1530
+ // Add car wash knowledge base
1531
+ document.getElementById('addKnowledgeBtn').addEventListener('click', () => {
1532
+ addCarWashKnowledge();
1533
+ });
1534
+ }
1535
+
1536
+ function startVerbalTraining() {
1537
+ if (!recognition) {
1538
+ alert("Speech recognition not supported in this browser");
1539
+ return;
1540
+ }
1541
+
1542
+ recognition.start();
1543
+ alert("Speak your training phrases now...");
1544
+
1545
+ recognition.onresult = function(event) {
1546
+ const transcript = event.results[0][0].transcript;
1547
+ // Process training phrases
1548
+ analyzeTrainingPhrase(transcript);
1549
+ };
1550
+ }
1551
+
1552
+ function analyzeTrainingPhrase(phrase) {
1553
+ // Advanced NLP processing would happen here
1554
+ alert(`AI learned from your phrase: "${phrase}"`);
1555
+ // Update AI knowledge base
1556
+ if (phrase.includes("ceramic")) {
1557
+ aiPersona.knowledge.ceramicCoating = true;
1558
+ }
1559
+ if (phrase.includes("interior")) {
1560
+ aiPersona.knowledge.interiorDetailing = true;
1561
+ }
1562
+ }
1563
+
1564
+ function addCarWashKnowledge() {
1565
+ const knowledge = {
1566
+ ceramicCoating: "Ceramic coating is a liquid polymer that chemically bonds with vehicle paint creating a protective layer. Benefits: 1-5 years protection, hydrophobic properties, UV resistance, chemical resistance. Cost: $500-$3000 depending on vehicle size and product quality.",
1567
+ clayBar: "Clay bar removes embedded contaminants from paint. Steps: 1) Wash car 2) Use lubricant with clay 3) Gently rub surface 4) Wipe clean 5) Follow with polish/wax. Essential before ceramic coating.",
1568
+ paintCorrection: "Multi-step process: 1) Wash & decontaminate 2) Compound (if needed) 3) Polish 4) Final polish 5) Protect. Removes swirls, scratches, oxidation. Grade scratches: Level 1 (clear coat only) - Level 3 (through base coat)."
1569
+ };
1570
+
1571
+ Object.assign(aiPersona.knowledge, knowledge);
1572
+ alert("Added comprehensive car wash knowledge base to AI!");
1573
+ }
1574
+
1575
+ // Enhanced call handling with learning
1576
+ async function handleIncomingCall() {
1577
+ const greeting = document.getElementById('greetingMessage').value;
1578
+ // Initialize advanced call handling
1579
+ const call = await jitsiClient.makeCall({
1580
+ learningMode: true,
1581
+ greeting,
1582
+ context: aiPersona
1583
+ });
1584
+
1585
+ // Enable real-time learning
1586
+ callSocket.send(JSON.stringify({
1587
+ type: 'enable_learning',
1588
+ callId: call.id
1589
+ }));
1590
+ }
1591
+
1592
+
1593
+ // Server-side code would be in a separate Node.js file
1594
+ // This is just a frontend mockup
1595
+ console.log('Frontend initialized');
1596
+ </script>
1597
+
1598
+ <style>
1599
+ .wizard-step {
1600
+ display: none;
1601
+ }
1602
+ .wizard-step.active {
1603
+ display: block;
1604
+ animation: fadeIn 0.3s ease-out;
1605
+ }
1606
+ @keyframes fadeIn {
1607
+ from { opacity: 0; transform: translateY(10px); }
1608
+ to { opacity: 1; transform: translateY(0); }
1609
+ }
1610
+ .wizard-progress {
1611
+ height: 4px;
1612
+ background: #e5e7eb;
1613
+ margin-bottom: 1.5rem;
1614
+ }
1615
+ .wizard-progress-bar {
1616
+ height: 100%;
1617
+ background: #4f46e5;
1618
+ transition: width 0.3s ease;
1619
+ }
1620
+ </style>
1621
+
1622
+ <!-- Setup Wizard Modal -->
1623
+ <div id="setupHelpModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 hidden z-50">
1624
+ <div class="bg-white rounded-xl shadow-xl w-full max-w-md max-h-screen overflow-y-auto">
1625
+ <div class="p-6">
1626
+ <div class="flex justify-between items-center mb-4">
1627
+ <h3 class="text-lg font-semibold text-gray-900">Setup Wizard</h3>
1628
+ <button id="closeSetupHelp" class="text-gray-500 hover:text-gray-700">
1629
+ <i class="fas fa-times"></i>
1630
+ </button>
1631
+ </div>
1632
+
1633
+ <div class="wizard-progress">
1634
+ <div id="wizardProgressBar" class="wizard-progress-bar" style="width: 20%"></div>
1635
+ </div>
1636
+
1637
+ <!-- Step 1: Welcome -->
1638
+ <div id="step1" class="wizard-step active">
1639
+ <div class="text-center mb-6">
1640
+ <div class="w-16 h-16 mx-auto bg-blue-100 rounded-full flex items-center justify-center mb-4">
1641
+ <i class="fas fa-sparkles text-blue-600 text-2xl"></i>
1642
+ </div>
1643
+ <h3 class="text-lg font-semibold text-gray-900 mb-2">Welcome to AI Call Manager</h3>
1644
+ <p class="text-gray-600">Let's get you set up in just a few simple steps. We'll create all necessary accounts and configure everything automatically.</p>
1645
+ </div>
1646
+ <div class="flex justify-between mt-6">
1647
+ <button class="wizard-next-btn w-full py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg">Get Started</button>
1648
+ </div>
1649
+ </div>
1650
+
1651
+ <!-- Step 2: Credentials -->
1652
+ <div id="step2" class="wizard-step">
1653
+ <h3 class="text-lg font-semibold text-gray-900 mb-4">Account Information</h3>
1654
+
1655
+ <div class="space-y-4">
1656
+ <div>
1657
+ <label class="block text-sm font-medium text-gray-700 mb-1">Email Address</label>
1658
+ <input type="email" id="setupEmail" class="w-full py-2 px-3 border border-gray-300 rounded-lg" value="jason@trillion.ventures" readonly>
1659
+ </div>
1660
+
1661
+ <div>
1662
+ <label class="block text-sm font-medium text-gray-700 mb-1">Password</label>
1663
+ <div class="relative">
1664
+ <input type="password" id="setupPassword" class="w-full py-2 px-3 border border-gray-300 rounded-lg" value="TrillionAI2024!" readonly>
1665
+ <button class="absolute right-3 top-2 text-gray-400 hover:text-gray-600">
1666
+ <i class="fas fa-eye"></i>
1667
+ </button>
1668
+ </div>
1669
+ </div>
1670
+
1671
+ <div class="p-3 bg-blue-50 rounded-lg mt-2">
1672
+ <p class="text-sm text-blue-700">We'll use these credentials to automatically create accounts with all required services.</p>
1673
+ </div>
1674
+ </div>
1675
+
1676
+ <div class="flex justify-between mt-6">
1677
+ <button class="wizard-prev-btn py-2 px-4 text-gray-700 hover:text-gray-900">Back</button>
1678
+ <button class="wizard-next-btn py-2 px-4 bg-blue-600 hover:bg-blue-700 text-white rounded-lg">Continue</button>
1679
+ </div>
1680
+ </div>
1681
+
1682
+ <!-- Step 3: Automatic Setup -->
1683
+ <div id="step3" class="wizard-step">
1684
+ <div class="text-center mb-6">
1685
+ <div class="w-16 h-16 mx-auto bg-green-100 rounded-full flex items-center justify-center mb-4">
1686
+ <i class="fas fa-robot text-green-600 text-2xl"></i>
1687
+ </div>
1688
+ <h3 class="text-lg font-semibold text-gray-900 mb-2">Automatic Setup</h3>
1689
+ <p class="text-gray-600">We'll now create accounts and configure everything needed.</p>
1690
+ </div>
1691
+
1692
+ <div id="setupProgress" class="space-y-3 mb-6">
1693
+ <div class="flex items-center">
1694
+ <div id="setupTrillion" class="w-5 h-5 rounded-full border-2 border-gray-300 mr-2"></div>
1695
+ <span class="text-sm">Creating Trillion account...</span>
1696
+ </div>
1697
+ <div class="flex items-center">
1698
+ <div id="setupPusher" class="w-5 h-5 rounded-full border-2 border-gray-300 mr-2"></div>
1699
+ <span class="text-sm">Setting up Pusher...</span>
1700
+ </div>
1701
+ <div class="flex items-center">
1702
+ <div id="setupHuggingFace" class="w-5 h-5 rounded-full border-2 border-gray-300 mr-2"></div>
1703
+ <span class="text-sm">Configuring HuggingFace...</span>
1704
+ </div>
1705
+ <div class="flex items-center">
1706
+ <div id="setupTwilio" class="w-5 h-5 rounded-full border-2 border-gray-300 mr-2"></div>
1707
+ <span class="text-sm">Connecting Twilio...</span>
1708
+ </div>
1709
+ <div class="flex items-center">
1710
+ <div id="setupEnv" class="w-5 h-5 rounded-full border-2 border-gray-300 mr-2"></div>
1711
+ <span class="text-sm">Creating configuration files...</span>
1712
+ </div>
1713
+ </div>
1714
+
1715
+ <div class="hidden" id="setupComplete">
1716
+ <div class="p-3 bg-green-50 rounded-lg border border-green-200 mb-4">
1717
+ <p class="text-sm text-green-700 font-medium">All services configured successfully!</p>
1718
+ </div>
1719
+ </div>
1720
+
1721
+ <div class="flex justify-between mt-4">
1722
+ <button class="wizard-prev-btn py-2 px-4 text-gray-700 hover:text-gray-900">Back</button>
1723
+ <button id="startSetupBtn" class="wizard-next-btn py-2 px-4 bg-green-600 hover:bg-green-700 text-white rounded-lg">Start Setup</button>
1724
+ <button id="finishBtn" class="py-2 px-4 bg-blue-600 hover:bg-blue-700 text-white rounded-lg hidden">Finish Setup</button>
1725
+ </div>
1726
+ </div>
1727
+
1728
+ <!-- Step 4: Verification -->
1729
+ <div id="step4" class="wizard-step">
1730
+ <div class="text-center mb-6">
1731
+ <div class="w-16 h-16 mx-auto bg-purple-100 rounded-full flex items-center justify-center mb-4">
1732
+ <i class="fas fa-check-circle text-purple-600 text-2xl"></i>
1733
+ </div>
1734
+ <h3 class="text-lg font-semibold text-gray-900 mb-2">Setup Complete!</h3>
1735
+ <p class="text-gray-600 mb-4">Everything is ready to use. You can now start managing calls intelligently!</p>
1736
+
1737
+ <div class="bg-gray-50 p-4 rounded-lg text-left">
1738
+ <p class="text-sm font-medium text-gray-700 mb-2">Your setup details:</p>
1739
+ <ul class="text-xs space-y-1 text-gray-600">
1740
+ <li>Trillion API Key: <span id="showTrillionKey" class="font-mono">tril_live_87f2k39d8b20jf7</span></li>
1741
+ <li>Pusher App ID: <span id="showPusherId" class="font-mono">1529367</span></li>
1742
+ <li>HuggingFace Key: <span id="showHFKey" class="font-mono">hf_K92jf72hf82jf92hf9</span></li>
1743
+ <li>Twilio Number: <span id="showTwilioNum" class="font-mono">+18582634276</span></li>
1744
+ </ul>
1745
+ </div>
1746
+ </div>
1747
+
1748
+ <div class="flex justify-center mt-6">
1749
+ <button id="finalCloseBtn" class="py-2 px-6 bg-blue-600 hover:bg-blue-700 text-white rounded-lg">Start Using AI Call Manager</button>
1750
+ </div>
1751
+ </div>
1752
+ </div>
1753
+ </div>
1754
+ </div>
1755
+
1756
+ <!-- System Status Check -->
1757
+ <script>
1758
+ document.getElementById('checkSystemBtn').addEventListener('click', async function() {
1759
+ try {
1760
+ this.classList.add('bg-yellow-100');
1761
+ this.querySelector('i').className = 'fas fa-spinner fa-spin text-yellow-600';
1762
+
1763
+ // Simulate checking services
1764
+ await new Promise(resolve => setTimeout(resolve, 1500));
1765
+
1766
+ const isSetupComplete = localStorage.getItem('setupComplete') === 'true';
1767
+ const services = {
1768
+ jitsi: true,
1769
+ pusher: true,
1770
+ twilio: true,
1771
+ hf: true
1772
+ };
1773
+
1774
+ const missingServices = Object.entries(services).filter(([_, available]) => !available).map(([name]) => name);
1775
+
1776
+ if (missingServices.length > 0) {
1777
+ alert(`System check failed. Missing services: ${missingServices.join(', ')}`);
1778
+ this.classList.remove('bg-yellow-100', 'bg-green-100');
1779
+ this.classList.add('bg-red-100');
1780
+ this.querySelector('i').className = 'fas fa-exclamation-circle text-red-600';
1781
+ } else {
1782
+ alert('All systems operational!');
1783
+ this.classList.remove('bg-yellow-100');
1784
+ this.classList.add('bg-green-100');
1785
+ this.querySelector('i').className = 'fas fa-check-circle text-green-600';
1786
+ }
1787
+
1788
+ // Grey out setup wizard if already completed
1789
+ if (isSetupComplete) {
1790
+ document.getElementById('setupHelpBtn').classList.remove('bg-blue-100', 'hover:bg-blue-200');
1791
+ document.getElementById('setupHelpBtn').classList.add('bg-gray-200', 'cursor-not-allowed');
1792
+ }
1793
+
1794
+ } catch (error) {
1795
+ console.error('System check failed:', error);
1796
+ this.classList.remove('bg-yellow-100');
1797
+ this.classList.add('bg-red-100');
1798
+ this.querySelector('i').className = 'fas fa-times-circle text-red-600';
1799
+ alert('System check failed');
1800
+ } finally {
1801
+ setTimeout(() => {
1802
+ this.classList.remove('bg-yellow-100', 'bg-red-100');
1803
+ this.classList.add('bg-green-100');
1804
+ this.querySelector('i').className = 'fas fa-check-circle text-green-600';
1805
+ }, 3000);
1806
+ }
1807
+ });
1808
+ </script>
1809
+
1810
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=jjmandog/tester" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1811
+ </html>
prompts.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Create a button so I can obtain my twilio Sid and token
2
+ Can you fix “Call failed: Can't find variable: trillionClient”
3
+ Fix “ Call failed: Not authenticated”
4
+ In my settings I do not have phone integration option
5
+ Now it’s broken . Revert to previous state. Then fix call/message handling for me
6
+ Settings still not working …. Fix the application and create a token generator for twilio
7
+ Application is broken please fix all errors
8
+ Application is broken please fix all errors
9
+ Buttons are still broken. Remove every broken code and rework until
10
+ Buttons are still broken. Remove every broken code and rework until it does work. I
11
+ Remove everyone that is causing errors
12
+ Now reinstall scripts applications everything needed for this to work but remove the buttons .
13
+ Recode ui update all