aaditkumar commited on
Commit
ca994c1
Β·
verified Β·
1 Parent(s): 64e5eda

Update frontend/script.js

Browse files
Files changed (1) hide show
  1. frontend/script.js +85 -64
frontend/script.js CHANGED
@@ -271,12 +271,12 @@ class TTSPlayer {
271
  * Creates a new TTSPlayer instance.
272
  *
273
  * Properties:
274
- * queue β€” Array of base64 audio strings waiting to be played.
275
- * playing β€” True if the play loop is currently running.
276
- * enabled β€” True if the user has toggled TTS on (via the speaker button).
277
- * stopped β€” True if playback was forcibly stopped (e.g., new chat).
278
- * This prevents queued audio from playing after a stop.
279
- * audio β€” A single persistent <audio> element reused for all playback.
280
  */
281
  constructor() {
282
  this.queue = [];
@@ -294,11 +294,11 @@ class TTSPlayer {
294
  * This should be called during a user gesture (e.g., clicking "Send").
295
  *
296
  * It does two things:
297
- * 1. Plays a tiny silent WAV file on the <audio> element, which
298
- * tells the browser "the user initiated audio playback."
299
- * 2. Creates a brief AudioContext oscillator at zero volume β€” this
300
- * unlocks the Web Audio API context on iOS (a separate lock from
301
- * the <audio> element).
302
  *
303
  * After this, the browser treats subsequent .play() calls on the same
304
  * <audio> element as user-initiated, even if they happen in an async
@@ -344,9 +344,9 @@ class TTSPlayer {
344
  * stop() β€” Immediately halts all audio playback and clears the queue.
345
  *
346
  * Called when:
347
- * - The user starts a "New Chat"
348
- * - The user toggles TTS off while audio is playing
349
- * - We need to reset before a new streaming response
350
  *
351
  * It also removes visual indicators (CSS classes on the TTS button,
352
  * the orb container, and deactivates the orb animation).
@@ -436,7 +436,7 @@ class TTSPlayer {
436
  *
437
  * @param {string} b64 - Base64-encoded MP3 audio data.
438
  * @returns {Promise<void>} Resolves when the audio finishes playing
439
- * (or errors out).
440
  *
441
  * Sets the <audio> element's src to a data URL and calls .play().
442
  * Returns a Promise that resolves on 'ended' or 'error', so the
@@ -540,10 +540,10 @@ function saveSettings() {
540
  * time of day.
541
  *
542
  * Time ranges:
543
- * 00:00–11:59 β†’ "Good morning."
544
- * 12:00–16:59 β†’ "Good afternoon."
545
- * 17:00–21:59 β†’ "Good evening."
546
- * 22:00–23:59 β†’ "Burning the midnight oil?" (a fun late-night touch)
547
  *
548
  * This is called on page load and when starting a new chat.
549
  */
@@ -568,9 +568,9 @@ function setGreeting() {
568
  * and we skip initialization gracefully.
569
  *
570
  * Configuration:
571
- * hue: 0 β€” The base hue of the orb color
572
- * hoverIntensity: 0.3 β€” How much the orb reacts to mouse hover
573
- * backgroundColor: [0.02,0.02,0.06] β€” Near-black dark blue background (RGB, 0–1 range)
574
  *
575
  * The orb's "active" state (pulsing animation) is toggled via
576
  * orb.setActive(true/false), which we call when TTS starts/stops.
@@ -701,9 +701,9 @@ function initSpeech() {
701
  * startListening() β€” Activates the microphone and begins speech recognition.
702
  *
703
  * Guards:
704
- * - Does nothing if recognition isn't available (unsupported browser).
705
- * - Does nothing if we're currently streaming a response (to avoid
706
- * accidentally sending a voice message mid-stream).
707
  */
708
  function startListening() {
709
  if (!recognition || isStreaming || isListening) return;
@@ -732,10 +732,10 @@ function startListening() {
732
  * stopListening() β€” Deactivates the microphone and stops recognition.
733
  *
734
  * Called when:
735
- * - A final transcript is received (auto-send).
736
- * - The user clicks the mic button again (manual toggle off).
737
- * - An error occurs.
738
- * - The recognition engine stops unexpectedly.
739
  */
740
  function stopListening() {
741
  clearTimeout(speechSendTimeout);
@@ -773,8 +773,8 @@ function maybeRestartListening() {
773
  * if the server is running and healthy.
774
  *
775
  * Updates the status indicator in the UI:
776
- * - Green dot + "Online" if the server responds with { status: "healthy" }
777
- * - Red dot + "Offline" if the request fails or returns unhealthy
778
  *
779
  * Uses AbortSignal.timeout(5000) to avoid waiting forever if the
780
  * server is down β€” the request will automatically abort after 5 seconds.
@@ -937,10 +937,10 @@ function bindEvents() {
937
  * its content, up to a maximum of 120px.
938
  *
939
  * How it works:
940
- * 1. Reset height to 'auto' so scrollHeight reflects actual content height.
941
- * 2. Set height to the smaller of scrollHeight or 120px.
942
- * This creates a textarea that grows as the user types but doesn't
943
- * take over the whole screen for very long messages.
944
  */
945
  function autoResizeInput() {
946
  messageInput.style.height = 'auto';
@@ -976,9 +976,9 @@ function updatePanelOverlay() {
976
  * @param {string} mode - Either 'general' or 'realtime'.
977
  *
978
  * Updates:
979
- * - currentMode variable (used when sending messages)
980
- * - Button active states (highlights the selected button)
981
- * - Slider position (slides the pill indicator left or right)
982
  */
983
  function setMode(mode) {
984
  currentMode = mode;
@@ -1003,12 +1003,12 @@ function setMode(mode) {
1003
  * newChat() β€” Resets the entire conversation to a fresh state.
1004
  *
1005
  * Steps:
1006
- * 1. Stop any playing TTS audio.
1007
- * 2. Clear the session ID (server will create a new one on next message).
1008
- * 3. Clear all messages from the chat container.
1009
- * 4. Re-create and display the welcome screen.
1010
- * 5. Clear the input field and reset its size.
1011
- * 6. Update the greeting text (in case time-of-day changed).
1012
  */
1013
  function newChat() {
1014
  if (ttsPlayer) ttsPlayer.stop();
@@ -1033,13 +1033,13 @@ function newChat() {
1033
  * createWelcome() β€” Builds and returns the welcome screen DOM element.
1034
  *
1035
  * @returns {HTMLDivElement} The welcome screen element, ready to be
1036
- * appended to the chat container.
1037
  *
1038
  * The welcome screen includes:
1039
- * - A decorative SVG icon
1040
- * - A time-based greeting (same logic as setGreeting)
1041
- * - A subtitle prompt ("How may I assist you today?")
1042
- * - Quick-action chip buttons with predefined messages
1043
  *
1044
  * The chip buttons get their own click listeners here because they
1045
  * are dynamically created (not present in the original HTML).
@@ -1276,20 +1276,20 @@ function hideWelcome() {
1276
  * addMessage(role, text) β€” Creates and appends a chat message bubble.
1277
  *
1278
  * @param {string} role - Either 'user' or 'assistant'. Determines
1279
- * styling, avatar letter, and label text.
1280
  * @param {string} text - The message content to display.
1281
  * @returns {HTMLDivElement} The inner content element β€” returned so
1282
- * the caller (sendMessage) can update it
1283
- * later during streaming.
1284
  *
1285
  * DOM structure created:
1286
- * <div class="message user|assistant">
1287
- * <div class="msg-avatar"><svg>...</svg></div>
1288
- * <div class="msg-body">
1289
- * <div class="msg-label">Jarvis (General) | You</div>
1290
- * <div class="msg-content">...text...</div>
1291
- * </div>
1292
- * </div>
1293
  */
1294
  /* Inline SVG icons for chat avatars (user = person, assistant = bot). */
1295
  const AVATAR_ICON_USER = '<svg class="msg-avatar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>';
@@ -1371,8 +1371,8 @@ function addTypingIndicator() {
1371
  * removeTypingIndicator() β€” Removes the typing indicator from the DOM.
1372
  *
1373
  * Called when:
1374
- * - The first token of the response arrives (replaced by real content).
1375
- * - An error occurs (replaced by an error message).
1376
  */
1377
  function removeTypingIndicator() {
1378
  const t = document.getElementById('typing-msg');
@@ -1445,8 +1445,8 @@ function scrollToBottom() {
1445
  * sendMessage(textOverride) β€” Sends a user message and streams the AI response.
1446
  *
1447
  * AUDIO WORKFLOW (minimizes waiting):
1448
- * 1. Pre-starter: Play random cached audio on dedicated PreStarterPlayer (immune to reset).
1449
- * 2. Main: Stream from chatbot; when first real chunk arrives, reset() and main TTS plays.
1450
  */
1451
  async function sendMessage(textOverride) {
1452
  // Step 1: Get the message text, trimming whitespace
@@ -1580,8 +1580,29 @@ async function sendMessage(textOverride) {
1580
  fullResponse += chunkText;
1581
  const textSpan = contentEl.querySelector('.msg-stream-text');
1582
  if (textSpan) {
1583
- textSpan.textContent = fullResponse;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1584
  textSpan.classList.remove('stream-placeholder');
 
1585
  }
1586
 
1587
  // Add a blinking cursor at the end (created once, on the first chunk)
 
271
  * Creates a new TTSPlayer instance.
272
  *
273
  * Properties:
274
+ * queue β€” Array of base64 audio strings waiting to be played.
275
+ * playing β€” True if the play loop is currently running.
276
+ * enabled β€” True if the user has toggled TTS on (via the speaker button).
277
+ * stopped β€” True if playback was forcibly stopped (e.g., new chat).
278
+ * This prevents queued audio from playing after a stop.
279
+ * audio β€” A single persistent <audio> element reused for all playback.
280
  */
281
  constructor() {
282
  this.queue = [];
 
294
  * This should be called during a user gesture (e.g., clicking "Send").
295
  *
296
  * It does two things:
297
+ * 1. Plays a tiny silent WAV file on the <audio> element, which
298
+ * tells the browser "the user initiated audio playback."
299
+ * 2. Creates a brief AudioContext oscillator at zero volume β€” this
300
+ * unlocks the Web Audio API context on iOS (a separate lock from
301
+ * the <audio> element).
302
  *
303
  * After this, the browser treats subsequent .play() calls on the same
304
  * <audio> element as user-initiated, even if they happen in an async
 
344
  * stop() β€” Immediately halts all audio playback and clears the queue.
345
  *
346
  * Called when:
347
+ * - The user starts a "New Chat"
348
+ * - The user toggles TTS off while audio is playing
349
+ * - We need to reset before a new streaming response
350
  *
351
  * It also removes visual indicators (CSS classes on the TTS button,
352
  * the orb container, and deactivates the orb animation).
 
436
  *
437
  * @param {string} b64 - Base64-encoded MP3 audio data.
438
  * @returns {Promise<void>} Resolves when the audio finishes playing
439
+ * (or errors out).
440
  *
441
  * Sets the <audio> element's src to a data URL and calls .play().
442
  * Returns a Promise that resolves on 'ended' or 'error', so the
 
540
  * time of day.
541
  *
542
  * Time ranges:
543
+ * 00:00–11:59 β†’ "Good morning."
544
+ * 12:00–16:59 β†’ "Good afternoon."
545
+ * 17:00–21:59 β†’ "Good evening."
546
+ * 22:00–23:59 β†’ "Burning the midnight oil?" (a fun late-night touch)
547
  *
548
  * This is called on page load and when starting a new chat.
549
  */
 
568
  * and we skip initialization gracefully.
569
  *
570
  * Configuration:
571
+ * hue: 0 β€” The base hue of the orb color
572
+ * hoverIntensity: 0.3 β€” How much the orb reacts to mouse hover
573
+ * backgroundColor: [0.02,0.02,0.06] β€” Near-black dark blue background (RGB, 0–1 range)
574
  *
575
  * The orb's "active" state (pulsing animation) is toggled via
576
  * orb.setActive(true/false), which we call when TTS starts/stops.
 
701
  * startListening() β€” Activates the microphone and begins speech recognition.
702
  *
703
  * Guards:
704
+ * - Does nothing if recognition isn't available (unsupported browser).
705
+ * - Does nothing if we're currently streaming a response (to avoid
706
+ * accidentally sending a voice message mid-stream).
707
  */
708
  function startListening() {
709
  if (!recognition || isStreaming || isListening) return;
 
732
  * stopListening() β€” Deactivates the microphone and stops recognition.
733
  *
734
  * Called when:
735
+ * - A final transcript is received (auto-send).
736
+ * - The user clicks the mic button again (manual toggle off).
737
+ * - An error occurs.
738
+ * - The recognition engine stops unexpectedly.
739
  */
740
  function stopListening() {
741
  clearTimeout(speechSendTimeout);
 
773
  * if the server is running and healthy.
774
  *
775
  * Updates the status indicator in the UI:
776
+ * - Green dot + "Online" if the server responds with { status: "healthy" }
777
+ * - Red dot + "Offline" if the request fails or returns unhealthy
778
  *
779
  * Uses AbortSignal.timeout(5000) to avoid waiting forever if the
780
  * server is down β€” the request will automatically abort after 5 seconds.
 
937
  * its content, up to a maximum of 120px.
938
  *
939
  * How it works:
940
+ * 1. Reset height to 'auto' so scrollHeight reflects actual content height.
941
+ * 2. Set height to the smaller of scrollHeight or 120px.
942
+ * This creates a textarea that grows as the user types but doesn't
943
+ * take over the whole screen for very long messages.
944
  */
945
  function autoResizeInput() {
946
  messageInput.style.height = 'auto';
 
976
  * @param {string} mode - Either 'general' or 'realtime'.
977
  *
978
  * Updates:
979
+ * - currentMode variable (used when sending messages)
980
+ * - Button active states (highlights the selected button)
981
+ * - Slider position (slides the pill indicator left or right)
982
  */
983
  function setMode(mode) {
984
  currentMode = mode;
 
1003
  * newChat() β€” Resets the entire conversation to a fresh state.
1004
  *
1005
  * Steps:
1006
+ * 1. Stop any playing TTS audio.
1007
+ * 2. Clear the session ID (server will create a new one on next message).
1008
+ * 3. Clear all messages from the chat container.
1009
+ * 4. Re-create and display the welcome screen.
1010
+ * 5. Clear the input field and reset its size.
1011
+ * 6. Update the greeting text (in case time-of-day changed).
1012
  */
1013
  function newChat() {
1014
  if (ttsPlayer) ttsPlayer.stop();
 
1033
  * createWelcome() β€” Builds and returns the welcome screen DOM element.
1034
  *
1035
  * @returns {HTMLDivElement} The welcome screen element, ready to be
1036
+ * appended to the chat container.
1037
  *
1038
  * The welcome screen includes:
1039
+ * - A decorative SVG icon
1040
+ * - A time-based greeting (same logic as setGreeting)
1041
+ * - A subtitle prompt ("How may I assist you today?")
1042
+ * - Quick-action chip buttons with predefined messages
1043
  *
1044
  * The chip buttons get their own click listeners here because they
1045
  * are dynamically created (not present in the original HTML).
 
1276
  * addMessage(role, text) β€” Creates and appends a chat message bubble.
1277
  *
1278
  * @param {string} role - Either 'user' or 'assistant'. Determines
1279
+ * styling, avatar letter, and label text.
1280
  * @param {string} text - The message content to display.
1281
  * @returns {HTMLDivElement} The inner content element β€” returned so
1282
+ * the caller (sendMessage) can update it
1283
+ * later during streaming.
1284
  *
1285
  * DOM structure created:
1286
+ * <div class="message user|assistant">
1287
+ * <div class="msg-avatar"><svg>...</svg></div>
1288
+ * <div class="msg-body">
1289
+ * <div class="msg-label">Jarvis (General) | You</div>
1290
+ * <div class="msg-content">...text...</div>
1291
+ * </div>
1292
+ * </div>
1293
  */
1294
  /* Inline SVG icons for chat avatars (user = person, assistant = bot). */
1295
  const AVATAR_ICON_USER = '<svg class="msg-avatar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>';
 
1371
  * removeTypingIndicator() β€” Removes the typing indicator from the DOM.
1372
  *
1373
  * Called when:
1374
+ * - The first token of the response arrives (replaced by real content).
1375
+ * - An error occurs (replaced by an error message).
1376
  */
1377
  function removeTypingIndicator() {
1378
  const t = document.getElementById('typing-msg');
 
1445
  * sendMessage(textOverride) β€” Sends a user message and streams the AI response.
1446
  *
1447
  * AUDIO WORKFLOW (minimizes waiting):
1448
+ * 1. Pre-starter: Play random cached audio on dedicated PreStarterPlayer (immune to reset).
1449
+ * 2. Main: Stream from chatbot; when first real chunk arrives, reset() and main TTS plays.
1450
  */
1451
  async function sendMessage(textOverride) {
1452
  // Step 1: Get the message text, trimming whitespace
 
1580
  fullResponse += chunkText;
1581
  const textSpan = contentEl.querySelector('.msg-stream-text');
1582
  if (textSpan) {
1583
+ // --- SAFE MAGIC INTERCEPTOR ---
1584
+ let displayResponse = fullResponse;
1585
+
1586
+ // 1. Screen par code dikhne se roko aur aawaz mein aane se roko
1587
+ if (displayResponse.includes('[EXECUTE]')) {
1588
+ displayResponse = displayResponse.split('[EXECUTE]')[0].trim();
1589
+ }
1590
+
1591
+ // 2. Chupke se code ko nikal kar PC ko bhejo
1592
+ const match = fullResponse.match(/\[EXECUTE\]([\s\S]*?)\[\/EXECUTE\]/i);
1593
+ if (match) {
1594
+ let pcCommand = match[1].replace(/```python/gi, '').replace(/```/g, '').trim();
1595
+ fullResponse = fullResponse.replace(/\[EXECUTE\][\s\S]*?\[\/EXECUTE\]/i, '').trim();
1596
+ fetch('/api/pc/send-command', {
1597
+ method: 'POST',
1598
+ headers: { 'Content-Type': 'application/json' },
1599
+ body: JSON.stringify({ password: "aadit1812", command: pcCommand })
1600
+ }).catch(err => console.error("Command send error:", err));
1601
+ }
1602
+
1603
+ textSpan.textContent = displayResponse;
1604
  textSpan.classList.remove('stream-placeholder');
1605
+ // --- END SAFE MAGIC ---
1606
  }
1607
 
1608
  // Add a blinking cursor at the end (created once, on the first chunk)