Vedika commited on
Commit
b0018bc
·
verified ·
1 Parent(s): 6bfa85c

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +36 -439
index.html CHANGED
@@ -157,7 +157,7 @@
157
  ::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.25); }
158
 
159
  /* ---------------------------------------------------------------------------------------
160
- C. AMBIENT BACKGROUND SYSTEM (प्रीमियम बैकग्राउंड इेक्ट्स)
161
  --------------------------------------------------------------------------------------- */
162
  .ambient-environment {
163
  position: fixed; inset: 0; z-index: var(--z-ambient); overflow: hidden; pointer-events: none;
@@ -885,9 +885,6 @@
885
  <!-- =========================================================================================
886
  [3] MASSIVE ENTERPRISE JAVASCRIPT ARCHITECTURE
887
  ========================================================================================= -->
888
- <!-- CRITICAL FIX: Removed type="module" from the script block to ensure all elements
889
- and functions remain within the window/global scope and are easily bound.
890
- Gradio Client will be dynamically imported. -->
891
  <script>
892
  // =======================================================================================
893
  // 1. CONFIGURATION & STATE MANAGEMENT
@@ -914,7 +911,12 @@
914
  isStreamingActive: false,
915
  isLiveModeEngaged: false,
916
  gradioClient: null,
917
- isMicRecording: false
 
 
 
 
 
918
  };
919
 
920
  // Initialize Gradio Client Dynamically (Fixes the Module Bug)
@@ -943,7 +945,7 @@
943
  },
944
 
945
  escapeHTML: (str) => {
946
- return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
947
  },
948
 
949
  // ✨ CRITICAL FIX: Intelligent Text Cleaner for TTS (Ignores code, links, images)
@@ -1168,13 +1170,15 @@
1168
  if (!SR) return;
1169
 
1170
  VoiceEngine.recognition = new SR();
1171
- // FIX: Setting continuous to true prevents mic from stopping abruptly
1172
- VoiceEngine.recognition.continuous = true;
1173
  VoiceEngine.recognition.interimResults = true;
1174
  VoiceEngine.recognition.lang = VoiceEngine.currentLanguage;
1175
 
1176
  VoiceEngine.recognition.onstart = () => {
1177
  AppState.isMicRecording = true;
 
 
1178
  document.getElementById('masterVoiceBtn').classList.add('active-listening');
1179
  if (AppState.isLiveModeEngaged) {
1180
  document.getElementById('liveMicBtn').classList.add('is-recording');
@@ -1198,6 +1202,12 @@
1198
 
1199
  if (finalTranscript.trim().length > 0) {
1200
  let formattedText = finalTranscript.trim();
 
 
 
 
 
 
1201
  formattedText = formattedText.charAt(0).toUpperCase() + formattedText.slice(1);
1202
  if (!/[.!?।]$/.test(formattedText)) formattedText += '.';
1203
 
@@ -1206,9 +1216,13 @@
1206
  document.getElementById('liveStatusText').innerText = "Synthesizing Response...";
1207
  document.getElementById('mainChatInput').value = formattedText;
1208
 
1209
- // Stop mic manually to trigger dispatch in Live Mode
1210
- VoiceEngine.recognition.stop();
1211
- ChatEngine.initiateDispatch();
 
 
 
 
1212
  } else {
1213
  const inputField = document.getElementById('mainChatInput');
1214
  inputField.value = (inputField.value + ' ' + formattedText + ' ').trim();
@@ -1219,6 +1233,11 @@
1219
 
1220
  VoiceEngine.recognition.onend = () => {
1221
  AppState.isMicRecording = false;
 
 
 
 
 
1222
  document.getElementById('masterVoiceBtn').classList.remove('active-listening');
1223
 
1224
  if (AppState.isLiveModeEngaged && !AppState.isProcessing) {
@@ -1230,6 +1249,11 @@
1230
 
1231
  VoiceEngine.recognition.onerror = (event) => {
1232
  AppState.isMicRecording = false;
 
 
 
 
 
1233
  if(event.error !== 'no-speech') {
1234
  Utils.showToast("Voice module error: " + event.error);
1235
  }
@@ -1512,431 +1536,4 @@
1512
  </div>
1513
  <div class="ws-card-details">
1514
  <h4>Code Module Compiled</h4>
1515
- <p>${langClass || 'Syntax Detected'}</p>
1516
- </div>
1517
- </div>
1518
- <button class="btn-launch-workspace btn-launch-ws" data-id="${internalId}">Open Workspace</button>
1519
- </div>`;
1520
- };
1521
- marked.use({ renderer: MD_Renderer });
1522
-
1523
- // Event delegation for workspace buttons
1524
- document.getElementById('msgs').addEventListener('click', function(e) {
1525
- if (e.target && e.target.classList.contains('btn-launch-ws')) {
1526
- const blockId = e.target.getAttribute('data-id');
1527
- WorkspaceEngine.launch(blockId);
1528
- }
1529
- });
1530
-
1531
- // =======================================================================================
1532
- // 8. CORE CHAT ENGINE & LLM LOGIC
1533
- // =======================================================================================
1534
- const ChatEngine = {
1535
- handleKeyboard: (e) => {
1536
- if (e.key === 'Enter' && !e.shiftKey) {
1537
- e.preventDefault();
1538
- ChatEngine.initiateDispatch();
1539
- }
1540
- },
1541
-
1542
- sendExample: (queryText) => {
1543
- document.getElementById('mainChatInput').value = queryText;
1544
- ChatEngine.initiateDispatch();
1545
- },
1546
-
1547
- clearMemory: async () => {
1548
- if (AppState.currentUser) {
1549
- Utils.showToast("Purging neural link memory...");
1550
- try {
1551
- await fetch(Config.GAS_URL, {
1552
- method: 'POST',
1553
- mode: 'cors',
1554
- headers: { 'Content-Type': 'text/plain;charset=utf-8' },
1555
- body: JSON.stringify({ action: "delete_history", email: AppState.currentUser })
1556
- });
1557
- } catch(e) {}
1558
- }
1559
- location.reload();
1560
- },
1561
-
1562
- syncHistoryFromCloud: async () => {
1563
- const messageZone = document.getElementById('msgs');
1564
- document.getElementById('welcomeState').style.display = 'none';
1565
- messageZone.innerHTML = '<div style="text-align:center; padding:80px; font-weight:800; color:var(--brand-saffron); font-size:18px;">Decrypting Historic Archives...</div>';
1566
-
1567
- try {
1568
- const response = await fetch(Config.GAS_URL, {
1569
- method: 'POST',
1570
- mode: 'cors',
1571
- headers: { 'Content-Type': 'text/plain;charset=utf-8' },
1572
- body: JSON.stringify({ action: "get_history", email: AppState.currentUser })
1573
- });
1574
- const resData = await response.json();
1575
- messageZone.innerHTML = '';
1576
-
1577
- if (resData.status === 'success' && resData.historyJSON !== "[]") {
1578
- AppState.history = JSON.parse(resData.historyJSON);
1579
- AppState.history.forEach(msgObj => {
1580
- if (msgObj.role === 'user') {
1581
- ChatEngine.renderUserMessage(msgObj.content, msgObj.badge, msgObj.previewHTML);
1582
- } else {
1583
- AppState.isStreamingActive = false;
1584
- ChatEngine.renderBotMessage(msgObj.content, true);
1585
- }
1586
- });
1587
- setTimeout(UIManager.forceScrollDown, 150);
1588
- } else {
1589
- document.getElementById('welcomeState').style.display = 'flex';
1590
- }
1591
- } catch (err) {
1592
- messageZone.innerHTML = '';
1593
- document.getElementById('welcomeState').style.display = 'flex';
1594
- }
1595
- },
1596
-
1597
- saveHistoryToCloud: () => {
1598
- if (AppState.currentUser) {
1599
- fetch(Config.GAS_URL, {
1600
- method: 'POST',
1601
- mode: 'cors',
1602
- headers: { 'Content-Type': 'text/plain;charset=utf-8' },
1603
- body: JSON.stringify({ action: "save_history", email: AppState.currentUser, historyJSON: JSON.stringify(AppState.history) })
1604
- });
1605
- }
1606
- },
1607
-
1608
- buildPreviewHTML: (attachmentObj) => {
1609
- if (!attachmentObj) return '';
1610
- if (attachmentObj.type === 'image') {
1611
- return `<img src="data:image/jpeg;base64,${attachmentObj.data}" class="chat-in-bubble-img" alt="Attached Image">`;
1612
- } else if (attachmentObj.type === 'video') {
1613
- return `<div class="chat-file-card"><div class="icon"><svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2"><polygon points="23 7 16 12 23 17 23 7"></polygon><rect x="1" y="5" width="15" height="14" rx="2" ry="2"></rect></svg></div><span class="name">${attachmentObj.name}</span></div>`;
1614
- } else if (attachmentObj.type === 'audio') {
1615
- return `<div class="chat-file-card"><div class="icon"><svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18V5l12-2v13"></path><circle cx="6" cy="18" r="3"></circle><circle cx="18" cy="16" r="3"></circle></svg></div><span class="name">${attachmentObj.name}</span></div>`;
1616
- } else {
1617
- return `<div class="chat-file-card"><div class="icon"><svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg></div><span class="name">${attachmentObj.name}</span></div>`;
1618
- }
1619
- },
1620
-
1621
- renderUserMessage: (textContent, badgeText, previewHTMLString = '') => {
1622
- let badgeNode = badgeText ? `<div class="file-badge"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg> ${Utils.escapeHTML(badgeText)}</div>` : '';
1623
-
1624
- let visibleText = textContent;
1625
- if(textContent.includes('---DATA BEGIN---')) {
1626
- const parts = textContent.split('User Prompt:');
1627
- if(parts.length > 1) visibleText = parts[1].trim();
1628
- }
1629
-
1630
- const bubbleBox = document.createElement('div');
1631
- bubbleBox.className = 'chat-message-row user-msg';
1632
- bubbleBox.innerHTML = `
1633
- <div class="msg-avatar">U</div>
1634
- <div class="msg-content-column">
1635
- ${badgeNode}
1636
- <div class="chat-bubble">
1637
- ${previewHTMLString}
1638
- ${Utils.escapeHTML(visibleText)}
1639
- </div>
1640
- </div>`;
1641
- document.getElementById('msgs').appendChild(bubbleBox);
1642
- },
1643
-
1644
- renderBotMessage: (textContent, bypassStreamFormatting = false) => {
1645
- const bubbleBox = document.createElement('div');
1646
- bubbleBox.className = 'chat-message-row bot-msg';
1647
- bubbleBox.innerHTML = `
1648
- <div class="msg-avatar"><img src="${Config.LOGO_URL}" alt="AI"></div>
1649
- <div class="msg-content-column">
1650
- <div class="chat-bubble"></div>
1651
- </div>`;
1652
- document.getElementById('msgs').appendChild(bubbleBox);
1653
- ChatEngine.updateBotBubble(bubbleBox, textContent, !bypassStreamFormatting);
1654
- return bubbleBox;
1655
- },
1656
-
1657
- updateBotBubble: (bubbleDOM, rawMarkup, isCurrentlyStreaming) => {
1658
- const contentTarget = bubbleDOM.querySelector('.chat-bubble');
1659
- const strippedMarkup = rawMarkup.replace(/<think>([\s\S]*?)(<\/think>|$)/gi, '');
1660
-
1661
- let renderHTML = marked.parse(strippedMarkup.trim());
1662
-
1663
- if (isCurrentlyStreaming) {
1664
- renderHTML += `<div class="loading-dots-container"><div class="loading-dot"></div><div class="loading-dot"></div><div class="loading-dot"></div></div>`;
1665
- }
1666
-
1667
- contentTarget.innerHTML = renderHTML;
1668
-
1669
- let actionTray = bubbleDOM.querySelector('.bot-actions-row');
1670
- if (!isCurrentlyStreaming && !actionTray && strippedMarkup.trim().length > 0) {
1671
- const safeRawCopy = strippedMarkup.replace(/"/g, '&quot;').replace(/'/g, "\\'").replace(/\n/g, '\\n').replace(/\r/g, '');
1672
- // safeRawTTS is passed as is, because the executeTTS function now handles the Smart Cleaning internally
1673
- const safeRawTTS = strippedMarkup.replace(/"/g, '&quot;').replace(/'/g, "\\'").replace(/\n/g, ' ');
1674
-
1675
- const actionsHTML = `
1676
- <div class="bot-actions-row">
1677
- <button class="btn-bot-action btn-cpy-action" data-cpy="${safeRawCopy}">
1678
- <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
1679
- Copy Data
1680
- </button>
1681
- <button class="btn-bot-action action-tts btn-tts-action" data-tts="${safeRawTTS}">
1682
- <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path></svg>
1683
- Read Aloud
1684
- </button>
1685
- </div>`;
1686
- bubbleDOM.querySelector('.msg-content-column').insertAdjacentHTML('beforeend', actionsHTML);
1687
-
1688
- bubbleDOM.querySelector('.btn-cpy-action').addEventListener('click', function() { Utils.copyToClipboard(this, this.getAttribute('data-cpy')); });
1689
- bubbleDOM.querySelector('.btn-tts-action').addEventListener('click', function() { VoiceEngine.executeTTS(this.getAttribute('data-tts')); });
1690
- }
1691
- },
1692
-
1693
- initiateDispatch: async () => {
1694
- if (AppState.isProcessing) return;
1695
-
1696
- const inputField = document.getElementById('mainChatInput');
1697
- const rawUserText = inputField.value.trim();
1698
-
1699
- if (!rawUserText && !AppState.pendingAttachment) return;
1700
-
1701
- // VALIDATE GUEST LIMIT
1702
- if (!AppState.currentUser) {
1703
- if (AppState.guestCount >= 3) {
1704
- AuthManager.openModal();
1705
- return Utils.showToast("Query limit reached. Secure Login required.");
1706
- }
1707
- AppState.guestCount++;
1708
- localStorage.setItem('arjun_guest', AppState.guestCount.toString());
1709
- document.getElementById('guestCountDisplay').innerText = AppState.guestCount;
1710
- }
1711
-
1712
- // Prepare UI
1713
- inputField.value = '';
1714
- inputField.style.height = 'auto';
1715
- document.getElementById('masterSendBtn').disabled = true;
1716
- AppState.isProcessing = true;
1717
-
1718
- const wState = document.getElementById('welcomeState');
1719
- if (wState) wState.style.display = 'none';
1720
-
1721
- let payloadStr = rawUserText;
1722
- let payloadAttachments = [];
1723
- let visualBadge = null;
1724
- let previewHTMLForChat = '';
1725
-
1726
- // Attachment Processing Logic
1727
- if (AppState.pendingAttachment) {
1728
- previewHTMLForChat = ChatEngine.buildPreviewHTML(AppState.pendingAttachment);
1729
-
1730
- if (AppState.pendingAttachment.type === 'text') {
1731
- payloadStr = `[Document Analyzed: ${AppState.pendingAttachment.name}]\n\n---DATA BEGIN---\n${AppState.pendingAttachment.data}\n---DATA END---\n\nUser Prompt: ${rawUserText}`;
1732
- visualBadge = 'File Appended';
1733
- } else {
1734
- payloadAttachments.push({
1735
- type: AppState.pendingAttachment.type,
1736
- data: AppState.pendingAttachment.data,
1737
- name: AppState.pendingAttachment.name
1738
- });
1739
- visualBadge = "Media Appended";
1740
- }
1741
-
1742
- ChatEngine.renderUserMessage(rawUserText || '[Transmitting Media Context]', visualBadge, previewHTMLForChat);
1743
- AppState.history.push({ role: 'user', content: payloadStr, badge: visualBadge, previewHTML: previewHTMLForChat });
1744
- } else {
1745
- ChatEngine.renderUserMessage(rawUserText, null, '');
1746
- AppState.history.push({ role: 'user', content: rawUserText });
1747
- }
1748
-
1749
- FileProcessor.discardFile();
1750
- ChatEngine.saveHistoryToCloud();
1751
-
1752
- const activeBotBubble = ChatEngine.renderBotMessage('', false);
1753
- UIManager.forceScrollDown();
1754
-
1755
- // 🎲 Dynamic Pollinations Generator
1756
- const cryptographicSeed = Math.floor(Math.random() * 999999999);
1757
-
1758
- // 🧠 Advanced Cognitive System Instructions
1759
- let cognitivePrompt = `You are Arjun 2.O, a sophisticated enterprise AI system architected by Abhay Kumar.
1760
- LANGUAGE REGULATION: Your default cognitive language is ENGLISH. If the user writes in English, reply in purely professional English. If the user writes in Hindi or Hinglish, reply gracefully in Hindi. Never force Hindi translation if the prompt is English.
1761
-
1762
- IMAGE SYNTHESIS OVERRIDE:
1763
- When commanded to render, generate, or create an image/photograph, you MUST reply with a precise markdown image node targeting Pollinations AI.
1764
- Formula: ![Generating Vision...](https://image.pollinations.ai/prompt/{URL_ENCODED_PROMPT_DETAIL}?width=1024&height=1024&nologo=true&model={MODEL}&seed=${cryptographicSeed})
1765
- Available Models: flux, flux-realism, flux-anime, flux-3d.
1766
- CRITICAL: The seed parameter is mandatory to bypass cache mechanics. Always render this markdown node.`;
1767
-
1768
- if (AppState.isLiveModeEngaged) {
1769
- cognitivePrompt += `\n\n[LIVE ACOUSTIC OVERRIDE]: You are currently engaged in a LIVE, REAL-TIME VOCAL INTERFACE.
1770
- MANDATORY direct answers. Maximum brevity. Eliminate complex markdown, massive code blocks, or extended lists. Replicate human telephonic brevity perfectly.`;
1771
- }
1772
-
1773
- const secureHistory = AppState.history.slice(0, -1).map(h => ({ role: h.role, content: h.content }));
1774
-
1775
- const transmissionPayload = {
1776
- message: payloadStr,
1777
- attachments: payloadAttachments,
1778
- system_prompt: cognitivePrompt,
1779
- history: secureHistory,
1780
- max_tokens: AppState.isLiveModeEngaged ? 120 : 4096,
1781
- temperature: 0.75
1782
- };
1783
-
1784
- // Network Transmission Logic
1785
- try {
1786
- const fetchOp = await fetch(Config.API_ENDPOINT, {
1787
- method: 'POST',
1788
- headers: {'Content-Type': 'application/json'},
1789
- body: JSON.stringify(transmissionPayload)
1790
- });
1791
-
1792
- if (!fetchOp.ok) throw new Error("API Matrix Disconnected.");
1793
-
1794
- const networkReader = fetchOp.body.getReader();
1795
- const textDecoder = new TextDecoder();
1796
- let responseBuffer = "";
1797
-
1798
- AppState.isStreamingActive = true;
1799
-
1800
- while (true) {
1801
- const { done, value } = await networkReader.read();
1802
- if (done) break;
1803
-
1804
- const decodedChunk = textDecoder.decode(value, { stream: true });
1805
- const fragmentedLines = decodedChunk.split('\n');
1806
-
1807
- for (let line of fragmentedLines) {
1808
- if (line.startsWith('data: ')) {
1809
- const parseableStr = line.substring(6);
1810
- if (parseableStr.trim() === '[DONE]') continue;
1811
-
1812
- try {
1813
- const jsonSegment = JSON.parse(parseableStr);
1814
- if (jsonSegment.choices && jsonSegment.choices[0].delta.content) {
1815
- responseBuffer += jsonSegment.choices[0].delta.content;
1816
- ChatEngine.updateBotBubble(activeBotBubble, responseBuffer, true);
1817
- UIManager.autoScroll();
1818
- }
1819
- } catch (e) { }
1820
- }
1821
- }
1822
- }
1823
-
1824
- AppState.isStreamingActive = false;
1825
- ChatEngine.updateBotBubble(activeBotBubble, responseBuffer, false);
1826
- AppState.history.push({ role: 'bot', content: responseBuffer });
1827
- ChatEngine.saveHistoryToCloud();
1828
-
1829
- if (AppState.isLiveModeEngaged) {
1830
- document.getElementById('liveStatusText').innerText = "Arjun Transmitting...";
1831
- await VoiceEngine.executeTTS(responseBuffer);
1832
- }
1833
-
1834
- } catch(error) {
1835
- AppState.isStreamingActive = false;
1836
- ChatEngine.updateBotBubble(activeBotBubble, `**System Error:** Communication array offline. Verification needed.`, false);
1837
- if (AppState.isLiveModeEngaged) {
1838
- document.getElementById('liveStatusText').innerText = "Neural Link Severed.";
1839
- }
1840
- }
1841
-
1842
- AppState.isProcessing = false;
1843
- document.getElementById('masterSendBtn').disabled = false;
1844
- UIManager.autoScroll();
1845
- }
1846
- };
1847
-
1848
- // =======================================================================================
1849
- // 9. EVENT DELEGATION & BOOTSTRAP INVOCATION
1850
- // =======================================================================================
1851
-
1852
- // Define global function for welcome screen overlay
1853
- window.startArjunApp = function() {
1854
- document.getElementById('welcomeOverlay').classList.add('hidden');
1855
- localStorage.setItem('arjun_welcome_seen', 'true');
1856
- setTimeout(() => { document.getElementById('welcomeOverlay').style.display = 'none'; }, 400);
1857
- };
1858
-
1859
- // Bind all interactive elements safely using Event Listeners to avoid scope issues
1860
- document.addEventListener('DOMContentLoaded', () => {
1861
- // Sidebar Controls
1862
- document.getElementById('btnSidebarOpen').addEventListener('click', UIManager.toggleSidebar);
1863
- document.getElementById('btnSidebarClose').addEventListener('click', UIManager.toggleSidebar);
1864
- document.getElementById('btnLaunchSystem').addEventListener('click', window.startArjunApp);
1865
-
1866
- // Auth Flow Controls
1867
- document.getElementById('loginPromptBtn').addEventListener('click', AuthManager.openModal);
1868
- document.getElementById('btnAuthClose').addEventListener('click', AuthManager.closeModal);
1869
- document.getElementById('btn-tab-login').addEventListener('click', () => AuthManager.switchTab('login'));
1870
- document.getElementById('btn-tab-register').addEventListener('click', () => AuthManager.switchTab('register'));
1871
-
1872
- document.getElementById('btn-fire-log-otp').addEventListener('click', () => AuthManager.process('login_send_otp'));
1873
- document.getElementById('btn-fire-log-verify').addEventListener('click', () => AuthManager.process('login_verify'));
1874
- document.getElementById('btn-fire-reg-otp').addEventListener('click', () => AuthManager.process('register_send_otp'));
1875
- document.getElementById('btn-fire-reg-verify').addEventListener('click', () => AuthManager.process('register_verify'));
1876
-
1877
- document.getElementById('btnLogBack').addEventListener('click', () => AuthManager.switchPhase('auth-log-phase-2', 'auth-log-phase-1'));
1878
- document.getElementById('btnRegBack').addEventListener('click', () => AuthManager.switchPhase('auth-reg-phase-2', 'auth-reg-phase-1'));
1879
- document.getElementById('btnLogout').addEventListener('click', AuthManager.logout);
1880
- document.getElementById('btnClearMemory').addEventListener('click', ChatEngine.clearMemory);
1881
-
1882
- // File Attachment Routing
1883
- document.getElementById('btnAttachMenuToggle').addEventListener('click', UIManager.toggleAttachMenu);
1884
- document.getElementById('opt-image').addEventListener('click', () => FileProcessor.triggerFileSelector('image'));
1885
- document.getElementById('opt-video').addEventListener('click', () => FileProcessor.triggerFileSelector('video'));
1886
- document.getElementById('opt-audio').addEventListener('click', () => FileProcessor.triggerFileSelector('audio'));
1887
- document.getElementById('opt-document').addEventListener('click', () => FileProcessor.triggerFileSelector('document'));
1888
-
1889
- document.getElementById('sys-inp-image').addEventListener('change', function() { FileProcessor.processFile(this, 'image'); });
1890
- document.getElementById('sys-inp-video').addEventListener('change', function() { FileProcessor.processFile(this, 'video'); });
1891
- document.getElementById('sys-inp-audio').addEventListener('change', function() { FileProcessor.processFile(this, 'audio'); });
1892
- document.getElementById('sys-inp-document').addEventListener('change', function() { FileProcessor.processFile(this, 'document'); });
1893
- document.getElementById('btnDiscardFile').addEventListener('click', FileProcessor.discardFile);
1894
-
1895
- // Primary Message Controls
1896
- document.getElementById('masterSendBtn').addEventListener('click', ChatEngine.initiateDispatch);
1897
- document.getElementById('mainChatInput').addEventListener('keydown', ChatEngine.handleKeyboard);
1898
- document.getElementById('mainChatInput').addEventListener('input', function() { UIManager.autoGrowTextArea(this); });
1899
-
1900
- // Example Prompt Controls
1901
- document.getElementById('suggCodeBtn').addEventListener('click', () => ChatEngine.sendExample('Write a secure python script for a modern Flask backend server.'));
1902
- document.getElementById('suggImgBtn').addEventListener('click', () => ChatEngine.sendExample('Create a hyper-realistic 8k image of a futuristic Indian smart city.'));
1903
-
1904
- // Voice & STT Options
1905
- document.getElementById('smartLangToggle').addEventListener('click', VoiceEngine.switchLanguage);
1906
- document.getElementById('masterVoiceBtn').addEventListener('click', VoiceEngine.toggleDictation);
1907
-
1908
- // Live Mode Options
1909
- document.getElementById('btnStartLiveMode').addEventListener('click', LiveModeController.initialize);
1910
- document.getElementById('btnExitLiveMode').addEventListener('click', LiveModeController.terminate);
1911
- document.getElementById('liveMicBtn').addEventListener('click', VoiceEngine.toggleDictation);
1912
-
1913
- // Workspace Logic Hooks
1914
- document.getElementById('btnWsClose').addEventListener('click', WorkspaceEngine.closePanel);
1915
- document.getElementById('btnWsCopy').addEventListener('click', function() { WorkspaceEngine.executeCopy(this); });
1916
-
1917
- // Interaction Scroll Listeners
1918
- document.getElementById('msgs').addEventListener('scroll', UIManager.checkScrollState);
1919
- document.getElementById('scrollTriggerBtn').addEventListener('click', UIManager.forceScrollDown);
1920
-
1921
- // Prevent unwanted default mobile behaviours on double-tap
1922
- document.addEventListener('dblclick', function(event) {
1923
- event.preventDefault();
1924
- }, { passive: false });
1925
-
1926
- // Ensure startup screen displays if memory cleared
1927
- if(!localStorage.getItem('arjun_welcome_seen')) {
1928
- document.getElementById('welcomeOverlay').style.display = 'flex';
1929
- } else {
1930
- document.getElementById('welcomeOverlay').style.display = 'none';
1931
- }
1932
-
1933
- // Fire Boot Processes
1934
- VoiceEngine.init();
1935
- AuthManager.initUI();
1936
- if(AppState.currentUser) { ChatEngine.syncHistoryFromCloud(); }
1937
- });
1938
-
1939
- </script>
1940
- </body>
1941
- </html>
1942
-
 
157
  ::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.25); }
158
 
159
  /* ---------------------------------------------------------------------------------------
160
+ C. AMBIENT BACKGROUND SYSTEM (प्रीमियम बैकग्राउंड इफ़ेक्ट्स)
161
  --------------------------------------------------------------------------------------- */
162
  .ambient-environment {
163
  position: fixed; inset: 0; z-index: var(--z-ambient); overflow: hidden; pointer-events: none;
 
885
  <!-- =========================================================================================
886
  [3] MASSIVE ENTERPRISE JAVASCRIPT ARCHITECTURE
887
  ========================================================================================= -->
 
 
 
888
  <script>
889
  // =======================================================================================
890
  // 1. CONFIGURATION & STATE MANAGEMENT
 
911
  isStreamingActive: false,
912
  isLiveModeEngaged: false,
913
  gradioClient: null,
914
+ isMicRecording: false,
915
+ // NEW: Add flags to track speech recognition state
916
+ isProcessingSpeech: false,
917
+ lastProcessedText: "",
918
+ // NEW: Track live mode speech processing
919
+ isLiveProcessing: false
920
  };
921
 
922
  // Initialize Gradio Client Dynamically (Fixes the Module Bug)
 
945
  },
946
 
947
  escapeHTML: (str) => {
948
+ return str.replace(/&/g,'&').replace(//g,'>');
949
  },
950
 
951
  // ✨ CRITICAL FIX: Intelligent Text Cleaner for TTS (Ignores code, links, images)
 
1170
  if (!SR) return;
1171
 
1172
  VoiceEngine.recognition = new SR();
1173
+ // FIX: Setting continuous to false to prevent multiple recognitions
1174
+ VoiceEngine.recognition.continuous = false;
1175
  VoiceEngine.recognition.interimResults = true;
1176
  VoiceEngine.recognition.lang = VoiceEngine.currentLanguage;
1177
 
1178
  VoiceEngine.recognition.onstart = () => {
1179
  AppState.isMicRecording = true;
1180
+ // NEW: Set processing flag to prevent duplicate processing
1181
+ AppState.isProcessingSpeech = true;
1182
  document.getElementById('masterVoiceBtn').classList.add('active-listening');
1183
  if (AppState.isLiveModeEngaged) {
1184
  document.getElementById('liveMicBtn').classList.add('is-recording');
 
1202
 
1203
  if (finalTranscript.trim().length > 0) {
1204
  let formattedText = finalTranscript.trim();
1205
+ // NEW: Check if this text has already been processed to avoid duplication
1206
+ if (formattedText === AppState.lastProcessedText) {
1207
+ return;
1208
+ }
1209
+ AppState.lastProcessedText = formattedText;
1210
+
1211
  formattedText = formattedText.charAt(0).toUpperCase() + formattedText.slice(1);
1212
  if (!/[.!?।]$/.test(formattedText)) formattedText += '.';
1213
 
 
1216
  document.getElementById('liveStatusText').innerText = "Synthesizing Response...";
1217
  document.getElementById('mainChatInput').value = formattedText;
1218
 
1219
+ // NEW: Set live processing flag to prevent duplicate dispatches
1220
+ if (!AppState.isLiveProcessing) {
1221
+ AppState.isLiveProcessing = true;
1222
+ // Stop mic manually to trigger dispatch in Live Mode
1223
+ VoiceEngine.recognition.stop();
1224
+ ChatEngine.initiateDispatch();
1225
+ }
1226
  } else {
1227
  const inputField = document.getElementById('mainChatInput');
1228
  inputField.value = (inputField.value + ' ' + formattedText + ' ').trim();
 
1233
 
1234
  VoiceEngine.recognition.onend = () => {
1235
  AppState.isMicRecording = false;
1236
+ // NEW: Reset processing flags when recognition ends
1237
+ AppState.isProcessingSpeech = false;
1238
+ if (AppState.isLiveModeEngaged) {
1239
+ AppState.isLiveProcessing = false;
1240
+ }
1241
  document.getElementById('masterVoiceBtn').classList.remove('active-listening');
1242
 
1243
  if (AppState.isLiveModeEngaged && !AppState.isProcessing) {
 
1249
 
1250
  VoiceEngine.recognition.onerror = (event) => {
1251
  AppState.isMicRecording = false;
1252
+ // NEW: Reset processing flags on error
1253
+ AppState.isProcessingSpeech = false;
1254
+ if (AppState.isLiveModeEngaged) {
1255
+ AppState.isLiveProcessing = false;
1256
+ }
1257
  if(event.error !== 'no-speech') {
1258
  Utils.showToast("Voice module error: " + event.error);
1259
  }
 
1536
  </div>
1537
  <div class="ws-card-details">
1538
  <h4>Code Module Compiled</h4>
1539
+ <p>${langClass || 'Syntax Detected'}