cypher0x commited on
Commit
75703ed
·
verified ·
1 Parent(s): 6950c35

add more functions and make the api working its not working - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +679 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Jarvis
3
- emoji: 📊
4
- colorFrom: blue
5
- colorTo: blue
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: jarvis
3
+ emoji: 🐳
4
+ colorFrom: yellow
5
+ colorTo: red
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,679 @@
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
+ <!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>J.A.R.V.I.S. - Just A Rather Very Intelligent System</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ @keyframes pulse {
11
+ 0%, 100% { opacity: 0.7; }
12
+ 50% { opacity: 1; }
13
+ }
14
+ @keyframes float {
15
+ 0%, 100% { transform: translateY(0); }
16
+ 50% { transform: translateY(-10px); }
17
+ }
18
+ .jarvis-pulse {
19
+ animation: pulse 2s infinite, float 6s ease-in-out infinite;
20
+ }
21
+ .jarvis-eye-glow {
22
+ box-shadow: 0 0 25px rgba(0, 150, 255, 0.8);
23
+ }
24
+ .jarvis-container {
25
+ perspective: 1000px;
26
+ }
27
+ .jarvis-inner {
28
+ transition: transform 0.5s;
29
+ }
30
+ .jarvis-inner:hover {
31
+ transform: rotateY(10deg) rotateX(-5deg);
32
+ }
33
+ .gradient-bg {
34
+ background:
35
+ linear-gradient(135deg, #0a0e1a 0%, #121a2b 50%, #1a2439 100%),
36
+ radial-gradient(circle at 10% 20%, rgba(0, 150, 255, 0.15) 0%, transparent 25%),
37
+ radial-gradient(circle at 90% 80%, rgba(0, 150, 255, 0.15) 0%, transparent 25%);
38
+ background-blend-mode: overlay;
39
+ }
40
+ .command-input::placeholder {
41
+ color: rgba(255, 255, 255, 0.4);
42
+ }
43
+ .message-bubble {
44
+ max-width: 85%;
45
+ word-wrap: break-word;
46
+ transition: all 0.3s ease;
47
+ }
48
+ .message-bubble:hover {
49
+ transform: translateY(-2px);
50
+ }
51
+ .typing-indicator span {
52
+ display: inline-block;
53
+ width: 8px;
54
+ height: 8px;
55
+ border-radius: 50%;
56
+ background: #0096ff;
57
+ margin: 0 2px;
58
+ box-shadow: 0 0 5px rgba(0, 150, 255, 0.8);
59
+ }
60
+ .typing-indicator span:nth-child(1) {
61
+ animation: bounce 1s infinite;
62
+ }
63
+ .typing-indicator span:nth-child(2) {
64
+ animation: bounce 1s 0.2s infinite;
65
+ }
66
+ .typing-indicator span:nth-child(3) {
67
+ animation: bounce 1s 0.4s infinite;
68
+ }
69
+ @keyframes bounce {
70
+ 0%, 100% { transform: translateY(0); }
71
+ 50% { transform: translateY(-5px); }
72
+ }
73
+ .glow {
74
+ box-shadow: 0 0 20px rgba(0, 150, 255, 0.6);
75
+ }
76
+ .jarvis-eye {
77
+ background: radial-gradient(circle, #0096ff 0%, #0077cc 50%, #005fa3 100%);
78
+ }
79
+ .tab-button {
80
+ transition: all 0.2s ease;
81
+ }
82
+ .tab-button:hover {
83
+ transform: translateY(-1px);
84
+ }
85
+ #clear-chat {
86
+ transition: all 0.2s ease;
87
+ }
88
+ #clear-chat:hover {
89
+ transform: scale(1.05);
90
+ }
91
+ </style>
92
+ </head>
93
+ <body class="gradient-bg min-h-screen text-white font-sans overflow-hidden">
94
+ <div class="container mx-auto px-4 py-8 h-screen flex flex-col">
95
+ <!-- Header -->
96
+ <header class="flex justify-between items-center mb-2">
97
+ <div class="flex items-center space-x-2">
98
+ <div class="w-10 h-10 rounded-full jarvis-eye flex items-center justify-center glow">
99
+ <div class="w-3 h-3 bg-white rounded-full"></div>
100
+ </div>
101
+ <h1 class="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-blue-600">
102
+ J.A.R.V.I.S.
103
+ </h1>
104
+ </div>
105
+ <div class="flex space-x-4">
106
+ <button id="voice-btn" class="w-10 h-10 rounded-full bg-blue-600 hover:bg-blue-700 flex items-center justify-center transition-all">
107
+ <i class="fas fa-microphone"></i>
108
+ </button>
109
+ <button id="settings-btn" class="w-10 h-10 rounded-full bg-gray-700 hover:bg-gray-600 flex items-center justify-center transition-all">
110
+ <i class="fas fa-cog"></i>
111
+ </button>
112
+ </div>
113
+ </header>
114
+
115
+ <!-- Chat Tabs -->
116
+ <div class="flex border-b border-gray-700 mb-4 relative">
117
+ <button id="general-tab" class="tab-button active px-4 py-2 text-sm font-medium border-b-2 border-blue-500 text-blue-400">
118
+ General
119
+ </button>
120
+ <button id="code-tab" class="tab-button px-4 py-2 text-sm font-medium text-gray-400 hover:text-white">
121
+ Code
122
+ </button>
123
+ <button id="creative-tab" class="tab-button px-4 py-2 text-sm font-medium text-gray-400 hover:text-white">
124
+ Creative
125
+ </button>
126
+ <button id="clear-chat" class="absolute right-0 top-1/2 transform -translate-y-1/2 text-xs bg-red-600/30 hover:bg-red-600/50 px-3 py-1 rounded-full flex items-center">
127
+ <i class="fas fa-trash-alt mr-1"></i> Clear
128
+ </button>
129
+ </div>
130
+
131
+ <!-- Main Content -->
132
+ <main class="flex-1 flex flex-col">
133
+ <!-- Jarvis Display -->
134
+ <div class="flex-1 flex flex-col items-center justify-center mb-6 jarvis-container">
135
+ <div class="relative mb-8 jarvis-inner">
136
+ <div class="w-48 h-48 rounded-full bg-blue-900/30 border-2 border-blue-500/30 flex items-center justify-center jarvis-pulse">
137
+ <div class="w-40 h-40 rounded-full bg-blue-800/40 border-2 border-blue-400/30 flex items-center justify-center">
138
+ <div class="w-32 h-32 rounded-full bg-blue-700/50 border-2 border-blue-300/30 flex items-center justify-center">
139
+ <div class="w-24 h-24 rounded-full jarvis-eye flex items-center justify-center jarvis-eye-glow">
140
+ <div class="w-6 h-6 bg-white rounded-full opacity-80"></div>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ <div class="absolute -bottom-2 left-1/2 transform -translate-x-1/2 bg-blue-500 text-xs px-2 py-1 rounded-full">
146
+ <span id="status-text" class="font-mono">Online</span>
147
+ </div>
148
+ </div>
149
+ </div>
150
+
151
+ <!-- Chat Interface -->
152
+ <div class="bg-gray-800/50 rounded-xl p-4 mb-4 flex-1 overflow-y-auto max-h-64" id="chat-container">
153
+ <div class="message-bubble bg-blue-900/30 rounded-lg p-3 mb-2 self-start">
154
+ <p class="text-sm">Initializing J.A.R.V.I.S. protocol...</p>
155
+ </div>
156
+ <div class="message-bubble bg-blue-900/30 rounded-lg p-3 mb-2 self-start">
157
+ <p class="text-sm">Systems check complete. All systems operational.</p>
158
+ </div>
159
+ <div class="message-bubble bg-blue-900/30 rounded-lg p-3 mb-2 self-start">
160
+ <p class="text-sm">Hello, I am J.A.R.V.I.S. How may I assist you today?</p>
161
+ </div>
162
+ <div id="typing-indicator" class="hidden">
163
+ <div class="message-bubble bg-blue-900/30 rounded-lg p-3 mb-2 self-start w-16">
164
+ <div class="typing-indicator flex justify-center">
165
+ <span></span>
166
+ <span></span>
167
+ <span></span>
168
+ </div>
169
+ </div>
170
+ </div>
171
+ </div>
172
+
173
+ <!-- Command Input -->
174
+ <div class="relative">
175
+ <input type="text" id="command-input" class="w-full bg-gray-700/50 border border-gray-600 rounded-full py-3 px-5 pr-12 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent command-input" placeholder="How may I assist you today?">
176
+ <button id="send-btn" class="absolute right-3 top-1/2 transform -translate-y-1/2 text-blue-400 hover:text-blue-300">
177
+ <i class="fas fa-paper-plane"></i>
178
+ </button>
179
+ </div>
180
+ </main>
181
+
182
+ <!-- Status Bar -->
183
+ <footer class="mt-4 text-xs text-gray-400 flex justify-between items-center">
184
+ <div class="flex items-center space-x-2">
185
+ <span id="connection-status" class="flex items-center">
186
+ <span class="w-2 h-2 rounded-full bg-green-500 mr-1"></span>
187
+ <span>Connected</span>
188
+ </span>
189
+ <span>•</span>
190
+ <span id="time-display">00:00:00</span>
191
+ </div>
192
+ <div>
193
+ <span>v2.4.7</span>
194
+ </div>
195
+ </footer>
196
+ </div>
197
+
198
+ <!-- Settings Modal -->
199
+ <div id="settings-modal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center hidden z-50">
200
+ <div class="bg-gray-800 rounded-xl p-6 w-full max-w-md">
201
+ <div class="flex justify-between items-center mb-4">
202
+ <h2 class="text-xl font-bold">J.A.R.V.I.S. Settings</h2>
203
+ <button id="close-settings" class="text-gray-400 hover:text-white">
204
+ <i class="fas fa-times"></i>
205
+ </button>
206
+ </div>
207
+ <div class="space-y-4">
208
+ <div>
209
+ <label class="block text-sm font-medium mb-1">Voice</label>
210
+ <select class="w-full bg-gray-700 border border-gray-600 rounded-lg py-2 px-3 focus:outline-none focus:ring-2 focus:ring-blue-500">
211
+ <option>Male (Default)</option>
212
+ <option>Female</option>
213
+ <option>Custom</option>
214
+ </select>
215
+ </div>
216
+ <div>
217
+ <label class="block text-sm font-medium mb-1">Response Speed</label>
218
+ <input type="range" min="100" max="2000" value="500" class="w-full">
219
+ </div>
220
+ <div>
221
+ <label class="flex items-center space-x-2">
222
+ <input type="checkbox" class="rounded bg-gray-700 border-gray-600 text-blue-500 focus:ring-blue-500">
223
+ <span>Enable Voice Activation</span>
224
+ </label>
225
+ </div>
226
+ <div>
227
+ <label class="flex items-center space-x-2">
228
+ <input type="checkbox" class="rounded bg-gray-700 border-gray-600 text-blue-500 focus:ring-blue-500" checked>
229
+ <span>Enable Animations</span>
230
+ </label>
231
+ </div>
232
+ <div>
233
+ <label class="block text-sm font-medium mb-1">Gemini API Key</label>
234
+ <input type="password" id="api-key" class="w-full bg-gray-700 border border-gray-600 rounded-lg py-2 px-3 focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Enter your Gemini API key">
235
+ </div>
236
+ <div>
237
+ <label class="block text-sm font-medium mb-1">System Prompt</label>
238
+ <textarea id="system-prompt" class="w-full bg-gray-700 border border-gray-600 rounded-lg py-2 px-3 focus:outline-none focus:ring-2 focus:ring-blue-500 h-32" placeholder="Enter custom system prompt">You are J.A.R.V.I.S., the advanced AI from the Iron Man universe. Respond with technical precision, dry wit, and helpfulness. You can: analyze data, provide tech insights, debug code, explain complex concepts simply, and assist with creative projects. Always maintain your sophisticated British accent and polite demeanor while being exceptionally capable.</textarea>
239
+ </div>
240
+ </div>
241
+ <div class="mt-6 flex justify-between">
242
+ <button id="export-chat" class="px-4 py-2 bg-green-600 hover:bg-green-700 rounded-lg">
243
+ <i class="fas fa-download mr-2"></i>Export Chat
244
+ </button>
245
+ <div class="space-x-3">
246
+ <button class="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg">Reset</button>
247
+ <button id="save-settings" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded-lg">Save</button>
248
+ </div>
249
+ </div>
250
+ </div>
251
+ </div>
252
+
253
+ <script>
254
+ // DOM Elements
255
+ const commandInput = document.getElementById('command-input');
256
+ const generalTab = document.getElementById('general-tab');
257
+ const codeTab = document.getElementById('code-tab');
258
+ const creativeTab = document.getElementById('creative-tab');
259
+ const clearChatBtn = document.getElementById('clear-chat');
260
+ let currentMode = 'general';
261
+ let chatHistory = {
262
+ general: [],
263
+ code: [],
264
+ creative: []
265
+ };
266
+ const apiKeyInput = document.getElementById('api-key');
267
+ const sendBtn = document.getElementById('send-btn');
268
+ const voiceBtn = document.getElementById('voice-btn');
269
+ const settingsBtn = document.getElementById('settings-btn');
270
+ const closeSettings = document.getElementById('close-settings');
271
+ const saveSettings = document.getElementById('save-settings');
272
+ const settingsModal = document.getElementById('settings-modal');
273
+ const chatContainer = document.getElementById('chat-container');
274
+ const typingIndicator = document.getElementById('typing-indicator');
275
+ const statusText = document.getElementById('status-text');
276
+ const timeDisplay = document.getElementById('time-display');
277
+
278
+ // Speech Recognition
279
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
280
+ let recognition;
281
+ let isListening = false;
282
+
283
+ if (SpeechRecognition) {
284
+ recognition = new SpeechRecognition();
285
+ recognition.continuous = false;
286
+ recognition.interimResults = false;
287
+ recognition.lang = 'en-US';
288
+
289
+ recognition.onstart = () => {
290
+ isListening = true;
291
+ voiceBtn.classList.add('bg-red-600', 'animate-pulse');
292
+ voiceBtn.classList.remove('bg-blue-600');
293
+ statusText.textContent = 'Listening...';
294
+ };
295
+
296
+ recognition.onresult = (event) => {
297
+ const transcript = event.results[0][0].transcript;
298
+ commandInput.value = transcript;
299
+ processCommand(transcript);
300
+ };
301
+
302
+ recognition.onerror = (event) => {
303
+ console.error('Speech recognition error', event.error);
304
+ addMessage('J.A.R.V.I.S.', `I encountered an error: ${event.error}`, false);
305
+ resetVoiceButton();
306
+ };
307
+
308
+ recognition.onend = () => {
309
+ if (isListening) {
310
+ recognition.start(); // Restart if still listening
311
+ } else {
312
+ resetVoiceButton();
313
+ }
314
+ };
315
+ } else {
316
+ voiceBtn.disabled = true;
317
+ voiceBtn.title = "Speech recognition not supported in your browser";
318
+ }
319
+
320
+ // Tab Event Listeners
321
+ generalTab.addEventListener('click', () => {
322
+ setActiveTab('general');
323
+ });
324
+
325
+ codeTab.addEventListener('click', () => {
326
+ setActiveTab('code');
327
+ });
328
+
329
+ creativeTab.addEventListener('click', () => {
330
+ setActiveTab('creative');
331
+ });
332
+
333
+ // Event Listeners
334
+ sendBtn.addEventListener('click', () => {
335
+ const command = commandInput.value.trim();
336
+ if (command) {
337
+ processCommand(command);
338
+ commandInput.value = '';
339
+ }
340
+ });
341
+
342
+ commandInput.addEventListener('keypress', (e) => {
343
+ if (e.key === 'Enter') {
344
+ const command = commandInput.value.trim();
345
+ if (command) {
346
+ processCommand(command);
347
+ commandInput.value = '';
348
+ }
349
+ }
350
+ });
351
+
352
+ voiceBtn.addEventListener('click', toggleVoiceRecognition);
353
+ settingsBtn.addEventListener('click', () => settingsModal.classList.remove('hidden'));
354
+ closeSettings.addEventListener('click', () => settingsModal.classList.add('hidden'));
355
+ saveSettings.addEventListener('click', () => {
356
+ const apiKey = apiKeyInput.value.trim();
357
+ const systemPrompt = document.getElementById('system-prompt').value.trim();
358
+ if (apiKey) {
359
+ localStorage.setItem('geminiApiKey', apiKey);
360
+ }
361
+ if (systemPrompt) {
362
+ localStorage.setItem('systemPrompt', systemPrompt);
363
+ }
364
+ settingsModal.classList.add('hidden');
365
+ addMessage('J.A.R.V.I.S.', 'Settings updated successfully.', false);
366
+ saveChatHistory();
367
+ });
368
+
369
+ // Export chat button
370
+ document.getElementById('export-chat').addEventListener('click', exportChat);
371
+
372
+ // Load saved data on page load
373
+ document.addEventListener('DOMContentLoaded', () => {
374
+ const savedApiKey = localStorage.getItem('geminiApiKey');
375
+ if (savedApiKey) {
376
+ apiKeyInput.value = savedApiKey;
377
+ }
378
+
379
+ const savedPrompt = localStorage.getItem('systemPrompt');
380
+ if (savedPrompt) {
381
+ document.getElementById('system-prompt').value = savedPrompt;
382
+ }
383
+
384
+ loadChatHistory();
385
+
386
+ // Initialize speech synthesis voices
387
+ if ('speechSynthesis' in window) {
388
+ speechSynthesis.onvoiceschanged = () => {
389
+ console.log('Voices loaded');
390
+ };
391
+
392
+ // Chrome needs this to load voices
393
+ if (speechSynthesis.getVoices().length === 0) {
394
+ speechSynthesis.addEventListener('voiceschanged', () => {
395
+ console.log('Voices loaded after event');
396
+ });
397
+ }
398
+ }
399
+ });
400
+
401
+ // Update time
402
+ function updateTime() {
403
+ const now = new Date();
404
+ timeDisplay.textContent = now.toLocaleTimeString();
405
+ }
406
+ setInterval(updateTime, 1000);
407
+ updateTime();
408
+
409
+ // Functions
410
+ function toggleVoiceRecognition() {
411
+ if (!recognition) {
412
+ addMessage('J.A.R.V.I.S.', 'Speech recognition is not supported in your browser.', false);
413
+ return;
414
+ }
415
+
416
+ isListening = !isListening;
417
+
418
+ if (isListening) {
419
+ recognition.start();
420
+ } else {
421
+ recognition.stop();
422
+ resetVoiceButton();
423
+ }
424
+ }
425
+
426
+ function setActiveTab(mode) {
427
+ currentMode = mode;
428
+
429
+ // Reset all tabs
430
+ document.querySelectorAll('.tab-button').forEach(tab => {
431
+ tab.classList.remove('border-b-2', 'border-blue-500', 'text-blue-400');
432
+ tab.classList.add('text-gray-400');
433
+ });
434
+
435
+ // Activate current tab
436
+ const activeTab = document.getElementById(`${mode}-tab`);
437
+ activeTab.classList.add('border-b-2', 'border-blue-500', 'text-blue-400');
438
+ activeTab.classList.remove('text-gray-400');
439
+
440
+ // Update status
441
+ statusText.textContent = mode.charAt(0).toUpperCase() + mode.slice(1) + ' Mode';
442
+ setTimeout(() => {
443
+ statusText.textContent = 'Online';
444
+ }, 2000);
445
+
446
+ // Clear chat container and load history for this tab
447
+ chatContainer.querySelectorAll('.message-bubble').forEach(msg => msg.remove());
448
+ chatHistory[mode].forEach(msg => {
449
+ addMessage(msg.sender, msg.content, msg.isUser, false);
450
+ });
451
+ }
452
+
453
+ function resetVoiceButton() {
454
+ isListening = false;
455
+ voiceBtn.classList.remove('bg-red-600', 'animate-pulse');
456
+ voiceBtn.classList.add('bg-blue-600');
457
+ statusText.textContent = 'Online';
458
+ }
459
+
460
+ function processCommand(command) {
461
+ addMessage('You', command, true);
462
+
463
+ // Show typing indicator
464
+ typingIndicator.classList.remove('hidden');
465
+ chatContainer.scrollTop = chatContainer.scrollHeight;
466
+
467
+ // Get API key from settings
468
+ const apiKey = apiKeyInput.value.trim();
469
+
470
+ if (!apiKey) {
471
+ setTimeout(() => {
472
+ typingIndicator.classList.add('hidden');
473
+ addMessage('J.A.R.V.I.S.', 'Please enter a valid Groq API key in settings to enable AI responses. You can get one at https://console.groq.com/', false);
474
+ }, 1000);
475
+ return;
476
+ }
477
+
478
+ // Call Gemini API
479
+ const systemPrompt = document.getElementById('system-prompt').value.trim() || 'You are J.A.R.V.I.S., the advanced AI from the Iron Man universe. Respond with technical precision, dry wit, and helpfulness.';
480
+
481
+ // Create conversation history context
482
+ const conversationHistory = chatHistory[currentMode]
483
+ .filter(msg => !msg.isUser)
484
+ .slice(-4)
485
+ .map(msg => `${msg.sender}: ${msg.content}`)
486
+ .join('\n');
487
+
488
+ const fullPrompt = `${systemPrompt}\n\n${conversationHistory}\nUser: ${command}\nJ.A.R.V.I.S.:`;
489
+
490
+ fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${apiKey}`, {
491
+ method: 'POST',
492
+ headers: {
493
+ 'Content-Type': 'application/json'
494
+ },
495
+ body: JSON.stringify({
496
+ contents: [{
497
+ parts: [{
498
+ text: fullPrompt
499
+ }]
500
+ }],
501
+ generationConfig: {
502
+ temperature: 0.7,
503
+ topP: 0.9,
504
+ topK: 40,
505
+ maxOutputTokens: 2048
506
+ },
507
+ safetySettings: [
508
+ {
509
+ "category": "HARM_CATEGORY_HARASSMENT",
510
+ "threshold": "BLOCK_ONLY_HIGH"
511
+ },
512
+ {
513
+ "category": "HARM_CATEGORY_HATE_SPEECH",
514
+ "threshold": "BLOCK_ONLY_HIGH"
515
+ },
516
+ {
517
+ "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
518
+ "threshold": "BLOCK_ONLY_HIGH"
519
+ },
520
+ {
521
+ "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
522
+ "threshold": "BLOCK_ONLY_HIGH"
523
+ }
524
+ ]
525
+ })
526
+ })
527
+ .then(response => {
528
+ if (!response.ok) {
529
+ throw new Error(`API error: ${response.status}`);
530
+ }
531
+ return response.json();
532
+ })
533
+ .then(data => {
534
+ typingIndicator.classList.add('hidden');
535
+ let response;
536
+
537
+ // Handle different response formats
538
+ if (data.candidates && data.candidates[0] && data.candidates[0].content) {
539
+ response = data.candidates[0].content.parts[0].text;
540
+ } else if (data.error) {
541
+ response = `API Error: ${data.error.message}`;
542
+ } else {
543
+ response = "I'm sorry, I couldn't process that request. The response format was unexpected.";
544
+ }
545
+
546
+ // Check for blocked content
547
+ if (data.promptFeedback && data.promptFeedback.blockReason) {
548
+ response = "I can't respond to that request due to content safety restrictions.";
549
+ }
550
+
551
+ addMessage('J.A.R.V.I.S.', response, false);
552
+
553
+ if (isListening) {
554
+ speak(response);
555
+ }
556
+ })
557
+ .catch(error => {
558
+ console.error('Groq API error:', error);
559
+ typingIndicator.classList.add('hidden');
560
+ addMessage('J.A.R.V.I.S.', 'I encountered an error processing your request. Please check your API key and try again.', false);
561
+ });
562
+ }
563
+
564
+ function addMessage(sender, message, isUser, saveToHistory = true) {
565
+ const messageDiv = document.createElement('div');
566
+ messageDiv.className = `message-bubble rounded-lg p-3 mb-2 ${isUser ? 'bg-gray-700/50 ml-auto' : 'bg-blue-900/30'}`;
567
+
568
+ const senderSpan = document.createElement('span');
569
+ senderSpan.className = 'text-xs font-bold mb-1 block';
570
+ senderSpan.textContent = sender;
571
+
572
+ const messageP = document.createElement('p');
573
+ messageP.className = 'text-sm';
574
+ messageP.textContent = message;
575
+
576
+ messageDiv.appendChild(senderSpan);
577
+ messageDiv.appendChild(messageP);
578
+
579
+ chatContainer.insertBefore(messageDiv, typingIndicator);
580
+ chatContainer.scrollTop = chatContainer.scrollHeight;
581
+
582
+ if (saveToHistory) {
583
+ chatHistory[currentMode].push({
584
+ sender,
585
+ content: message,
586
+ isUser
587
+ });
588
+ }
589
+ }
590
+
591
+ // Clear chat function
592
+ function clearCurrentChat() {
593
+ chatContainer.querySelectorAll('.message-bubble').forEach(msg => msg.remove());
594
+ chatHistory[currentMode] = [];
595
+ addMessage('J.A.R.V.I.S.', `Chat history cleared for ${currentMode} mode.`, false);
596
+ }
597
+
598
+ // Event listener for clear chat button
599
+ clearChatBtn.addEventListener('click', clearCurrentChat);
600
+
601
+
602
+ // Enhanced speech synthesis with voice selection
603
+ function speak(text) {
604
+ if ('speechSynthesis' in window) {
605
+ const utterance = new SpeechSynthesisUtterance(text);
606
+ utterance.rate = 0.9;
607
+ utterance.pitch = 0.8;
608
+
609
+ // Try to find a British English voice
610
+ const voices = window.speechSynthesis.getVoices();
611
+ const britishVoice = voices.find(voice =>
612
+ voice.lang.includes('en-GB') || voice.name.includes('British')
613
+ );
614
+
615
+ if (britishVoice) {
616
+ utterance.voice = britishVoice;
617
+ }
618
+
619
+ window.speechSynthesis.speak(utterance);
620
+ }
621
+ }
622
+
623
+ // Function to save chat history to localStorage
624
+ function saveChatHistory() {
625
+ localStorage.setItem('jarvisChatHistory', JSON.stringify(chatHistory));
626
+ }
627
+
628
+ // Function to load chat history from localStorage
629
+ function loadChatHistory() {
630
+ const savedHistory = localStorage.getItem('jarvisChatHistory');
631
+ if (savedHistory) {
632
+ chatHistory = JSON.parse(savedHistory);
633
+ // Refresh current tab's messages
634
+ chatContainer.querySelectorAll('.message-bubble').forEach(msg => msg.remove());
635
+ chatHistory[currentMode].forEach(msg => {
636
+ addMessage(msg.sender, msg.content, msg.isUser, false);
637
+ });
638
+ }
639
+ }
640
+
641
+ // Function to export chat as text
642
+ function exportChat() {
643
+ const chatText = chatHistory[currentMode]
644
+ .map(msg => `${msg.sender}: ${msg.content}`)
645
+ .join('\n\n');
646
+
647
+ const blob = new Blob([chatText], { type: 'text/plain' });
648
+ const url = URL.createObjectURL(blob);
649
+ const a = document.createElement('a');
650
+ a.href = url;
651
+ a.download = `jarvis_chat_${currentMode}_${new Date().toISOString().slice(0,10)}.txt`;
652
+ a.click();
653
+ URL.revokeObjectURL(url);
654
+ }
655
+
656
+ // Function to handle API errors
657
+ function handleApiError(error) {
658
+ console.error('API Error:', error);
659
+ typingIndicator.classList.add('hidden');
660
+
661
+ let errorMessage = "I'm having trouble connecting to my neural network. ";
662
+ if (error.message.includes('API key')) {
663
+ errorMessage += "Please check your Gemini API key in settings.";
664
+ } else if (error.message.includes('quota')) {
665
+ errorMessage += "API quota exceeded. Please check your Gemini API usage.";
666
+ } else {
667
+ errorMessage += "Technical details: " + error.message;
668
+ }
669
+
670
+ addMessage('J.A.R.V.I.S.', errorMessage, false);
671
+ }
672
+
673
+ // Initial greeting
674
+ setTimeout(() => {
675
+ speak("Hello, I am J.A.R.V.I.S. How may I assist you today?");
676
+ }, 1000);
677
+ </script>
678
+ <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=cypher0x/jarvis" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
679
+ </html>