Vedika commited on
Commit
92bb864
·
verified ·
1 Parent(s): 5df859e

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +112 -52
index.html CHANGED
@@ -1,3 +1,4 @@
 
1
  <!DOCTYPE html>
2
  <html lang="en" dir="ltr">
3
  <head>
@@ -10,7 +11,7 @@
10
  <title>Arjun 2.O - Professional Advanced AI</title>
11
 
12
  <!-- =========================================================================================
13
- 1. EXTERNAL RESOURCES & LIBRARIES (बाहरी स्रोत और लाइब्रेरीज़)
14
  ========================================================================================= -->
15
  <!-- Preconnect for Performance -->
16
  <link rel="preconnect" href="https://fonts.googleapis.com">
@@ -29,14 +30,14 @@
29
  <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.1/marked.min.js"></script>
30
 
31
  <!-- =========================================================================================
32
- 2. MASSIVE CSS ARCHITECTURE (विस्तृत स्टाइलिंग और एनीमेशन)
33
  ========================================================================================= -->
34
  <style>
35
  /* ---------------------------------------------------------------------------------------
36
  A. CSS VARIABLES & DESIGN TOKENS
37
  --------------------------------------------------------------------------------------- */
38
  :root {
39
- /* Branding: Professional Tiranga Theme */
40
  --brand-saffron: #FF9933;
41
  --brand-saffron-light: rgba(255, 153, 51, 0.12);
42
  --brand-saffron-hover: #e68a2e;
@@ -961,7 +962,7 @@
961
  align-items: flex-end;
962
  }
963
 
964
- /* NEW: In-Message File Preview Cards */
965
  .chat-in-bubble-img {
966
  max-width: 300px;
967
  max-height: 300px;
@@ -1365,7 +1366,7 @@
1365
  font-weight: 400;
1366
  }
1367
 
1368
- /* Attachment Dropdown Menu (Gemini Style) */
1369
  .attachment-module {
1370
  position: relative;
1371
  }
@@ -1813,7 +1814,7 @@
1813
  .workspace-editor-surface pre {
1814
  margin: 0;
1815
  padding: 28px;
1816
- background: #282c34; /* Atom One Dark BG */
1817
  border: 1px solid var(--border-light);
1818
  border-radius: var(--radius-lg);
1819
  font-family: var(--font-mono);
@@ -1981,18 +1982,6 @@
1981
  @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
1982
  @keyframes slideIn { from { opacity: 0; transform: translateX(25px); } to { opacity: 1; transform: none; } }
1983
 
1984
- /* Blinking Cursor for Typing */
1985
- .typing-cursor {
1986
- display: inline-block;
1987
- width: 10px;
1988
- height: 18px;
1989
- background: var(--brand-saffron);
1990
- margin-left: 4px;
1991
- animation: cursorBlink 1s step-end infinite;
1992
- vertical-align: middle;
1993
- }
1994
- @keyframes cursorBlink { 50% { opacity: 0; } }
1995
-
1996
  /* Loading Dots */
1997
  .loading-dots-container {
1998
  display: flex;
@@ -2355,7 +2344,7 @@
2355
  </div>
2356
 
2357
  <!-- =========================================================================================
2358
- 7. ENTERPRISE JAVASCRIPT LOGIC (पूर्ण आर्किटेक्चर)
2359
  ========================================================================================= -->
2360
  <script>
2361
  /**
@@ -2594,11 +2583,12 @@
2594
  });
2595
 
2596
  /**
2597
- * Voice & Speech Engine (Smart Bilingual Toggle)
2598
  */
2599
  const VoiceEngine = {
2600
  recognition: null,
2601
  currentLanguage: 'en-IN',
 
2602
 
2603
  init: () => {
2604
  const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
@@ -2621,7 +2611,7 @@
2621
  VoiceEngine.recognition.onresult = (event) => {
2622
  let transcript = '';
2623
  for (let i = event.resultIndex; i < event.results.length; ++i) {
2624
- transcript += event.results[i][0].transcript;
2625
  }
2626
  transcript = transcript.trim();
2627
  if (transcript.length > 0) {
@@ -2667,9 +2657,9 @@
2667
 
2668
  if (VoiceEngine.currentLanguage === 'en-IN') {
2669
  VoiceEngine.currentLanguage = 'hi-IN';
2670
- badge.innerText = 'हि';
2671
  btn.classList.add('hindi-active');
2672
- Utils.showToast("Acoustic Protocol: Pure Hindi (देवनागरी)");
2673
  } else {
2674
  VoiceEngine.currentLanguage = 'en-IN';
2675
  badge.innerText = 'EN';
@@ -2692,25 +2682,88 @@
2692
  try { VoiceEngine.recognition.start(); } catch (e) { VoiceEngine.recognition.stop(); }
2693
  },
2694
 
2695
- // Calling Backend TTS
 
 
2696
  executeTTS: async (text) => {
2697
- const cleanText = text.replace(/[*_~`#]/g, '').replace(/<[^>]*>?/gm, '');
2698
- Utils.showToast("🔊 Linking with Neural Voice Matrix...");
2699
- try {
2700
- const response = await fetch('/api/tts', {
2701
- method: 'POST',
2702
- headers: { 'Content-Type': 'application/json' },
2703
- body: JSON.stringify({ text: cleanText })
2704
- });
2705
- if (!response.ok) throw new Error("Backend Synthesis Fault");
 
 
 
2706
 
2707
- const blob = await response.blob();
2708
- const audioUrl = URL.createObjectURL(blob);
2709
- const audio = new Audio(audioUrl);
2710
- audio.play();
2711
- } catch (error) {
2712
- Utils.showToast("Neural link failed. Verify backend integrity.");
2713
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2714
  }
2715
  };
2716
  VoiceEngine.init();
@@ -2731,6 +2784,13 @@
2731
  terminate: () => {
2732
  AppState.isLiveModeEngaged = false;
2733
  document.getElementById('liveOverlay').classList.remove('active');
 
 
 
 
 
 
 
2734
  if (VoiceEngine.recognition) {
2735
  try { VoiceEngine.recognition.stop(); } catch(e){}
2736
  }
@@ -2747,7 +2807,7 @@
2747
  },
2748
 
2749
  processFile: async (inputElement, typeContext) => {
2750
- const file = inputElement.files[0];
2751
  if (!file) return;
2752
 
2753
  const fName = file.name.toLowerCase();
@@ -2774,7 +2834,7 @@
2774
 
2775
  if (typeContext === 'image') {
2776
  fileReader.onload = (e) => {
2777
- AppState.pendingAttachment = { type: 'image', data: e.target.result.split(',')[1], name: file.name };
2778
  thumbImg.src = e.target.result;
2779
  thumbImg.style.display = 'flex';
2780
  };
@@ -2782,7 +2842,7 @@
2782
  }
2783
  else if (typeContext === 'video' || typeContext === 'audio') {
2784
  fileReader.onload = (e) => {
2785
- AppState.pendingAttachment = { type: typeContext, data: e.target.result.split(',')[1], name: file.name };
2786
  docIcon.innerText = typeContext === 'video' ? '🎥' : '🎵';
2787
  docIcon.style.display = 'flex';
2788
  };
@@ -2882,7 +2942,7 @@
2882
  const MD_Renderer = new marked.Renderer();
2883
  MD_Renderer.code = function(token) {
2884
  const rawCode = typeof token === 'string' ? token : (token.text || '');
2885
- const langClass = typeof token === 'string' ? arguments[1] : (token.lang || '');
2886
 
2887
  // Render beautiful loading box during stream
2888
  if (AppState.isStreamingActive) {
@@ -2946,7 +3006,7 @@
2946
  syncHistoryFromCloud: async () => {
2947
  const messageZone = document.getElementById('msgs');
2948
  document.getElementById('welcomeState').style.display = 'none';
2949
- messageZone.innerHTML = '<div style="text-align:center; padding:80px; font-weight:800; color:var(--brand-saffron); font-size:18px;">Decrypting Historic Archives...</div>';
2950
 
2951
  try {
2952
  const response = await fetch(Config.GAS_URL, {
@@ -3000,7 +3060,7 @@
3000
  },
3001
 
3002
  renderUserMessage: (textContent, badgeText, previewHTMLString = '') => {
3003
- let badgeNode = badgeText ? `<div class="file-badge">${Utils.escapeHTML(badgeText)}</div>` : '';
3004
  const bubbleBox = document.createElement('div');
3005
  bubbleBox.className = 'chat-message-row user-msg';
3006
  bubbleBox.innerHTML = `
@@ -3163,7 +3223,7 @@
3163
  attachments: payloadAttachments,
3164
  system_prompt: cognitivePrompt,
3165
  history: secureHistory,
3166
- max_tokens: AppState.isLiveModeEngaged ? 120 : 4096,
3167
  temperature: 0.75
3168
  };
3169
 
@@ -3197,8 +3257,8 @@
3197
 
3198
  try {
3199
  const jsonSegment = JSON.parse(parseableStr);
3200
- if (jsonSegment.choices && jsonSegment.choices[0].delta.content) {
3201
- responseBuffer += jsonSegment.choices[0].delta.content;
3202
  ChatEngine.updateBotBubble(activeBotBubble, responseBuffer, true);
3203
  UIManager.autoScroll();
3204
  }
@@ -3213,9 +3273,9 @@
3213
  ChatEngine.saveHistoryToCloud();
3214
 
3215
  if (AppState.isLiveModeEngaged) {
3216
- document.getElementById('liveStatusText').innerText = "Arjun Transmitting...";
 
3217
  await VoiceEngine.executeTTS(responseBuffer);
3218
- document.getElementById('liveStatusText').innerText = "Tap mic to respond";
3219
  }
3220
 
3221
  } catch(error) {
@@ -3239,4 +3299,4 @@
3239
 
3240
  </script>
3241
  </body>
3242
- </html>
 
1
+
2
  <!DOCTYPE html>
3
  <html lang="en" dir="ltr">
4
  <head>
 
11
  <title>Arjun 2.O - Professional Advanced AI</title>
12
 
13
  <!-- =========================================================================================
14
+ 1. EXTERNAL RESOURCES & LIBRARIES
15
  ========================================================================================= -->
16
  <!-- Preconnect for Performance -->
17
  <link rel="preconnect" href="https://fonts.googleapis.com">
 
30
  <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.1/marked.min.js"></script>
31
 
32
  <!-- =========================================================================================
33
+ 2. MASSIVE CSS ARCHITECTURE
34
  ========================================================================================= -->
35
  <style>
36
  /* ---------------------------------------------------------------------------------------
37
  A. CSS VARIABLES & DESIGN TOKENS
38
  --------------------------------------------------------------------------------------- */
39
  :root {
40
+ /* Branding: Professional Theme */
41
  --brand-saffron: #FF9933;
42
  --brand-saffron-light: rgba(255, 153, 51, 0.12);
43
  --brand-saffron-hover: #e68a2e;
 
962
  align-items: flex-end;
963
  }
964
 
965
+ /* In-Message File Preview Cards */
966
  .chat-in-bubble-img {
967
  max-width: 300px;
968
  max-height: 300px;
 
1366
  font-weight: 400;
1367
  }
1368
 
1369
+ /* Attachment Dropdown Menu */
1370
  .attachment-module {
1371
  position: relative;
1372
  }
 
1814
  .workspace-editor-surface pre {
1815
  margin: 0;
1816
  padding: 28px;
1817
+ background: #282c34;
1818
  border: 1px solid var(--border-light);
1819
  border-radius: var(--radius-lg);
1820
  font-family: var(--font-mono);
 
1982
  @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
1983
  @keyframes slideIn { from { opacity: 0; transform: translateX(25px); } to { opacity: 1; transform: none; } }
1984
 
 
 
 
 
 
 
 
 
 
 
 
 
1985
  /* Loading Dots */
1986
  .loading-dots-container {
1987
  display: flex;
 
2344
  </div>
2345
 
2346
  <!-- =========================================================================================
2347
+ 7. ENTERPRISE JAVASCRIPT LOGIC (ADVANCED GRADIO INTEGRATION)
2348
  ========================================================================================= -->
2349
  <script>
2350
  /**
 
2583
  });
2584
 
2585
  /**
2586
+ * Voice & Speech Engine (Smart Bilingual Toggle & GRADIO EDGE-TTS)
2587
  */
2588
  const VoiceEngine = {
2589
  recognition: null,
2590
  currentLanguage: 'en-IN',
2591
+ currentAudioNode: null,
2592
 
2593
  init: () => {
2594
  const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
 
2611
  VoiceEngine.recognition.onresult = (event) => {
2612
  let transcript = '';
2613
  for (let i = event.resultIndex; i < event.results.length; ++i) {
2614
+ transcript += event.results[i].transcript;
2615
  }
2616
  transcript = transcript.trim();
2617
  if (transcript.length > 0) {
 
2657
 
2658
  if (VoiceEngine.currentLanguage === 'en-IN') {
2659
  VoiceEngine.currentLanguage = 'hi-IN';
2660
+ badge.innerText = 'HI';
2661
  btn.classList.add('hindi-active');
2662
+ Utils.showToast("Acoustic Protocol: Pure Hindi / Hinglish");
2663
  } else {
2664
  VoiceEngine.currentLanguage = 'en-IN';
2665
  badge.innerText = 'EN';
 
2682
  try { VoiceEngine.recognition.start(); } catch (e) { VoiceEngine.recognition.stop(); }
2683
  },
2684
 
2685
+ // -----------------------------------------------------------------------------------
2686
+ // GRADIO EDGE-TTS INTEGRATION (REPLACED OLD LOGIC WITH REQUESTED IMPLEMENTATION)
2687
+ // -----------------------------------------------------------------------------------
2688
  executeTTS: async (text) => {
2689
+ return new Promise(async (resolve) => {
2690
+ // Clean text payload
2691
+ const cleanText = text.replace(/[*_~`#]/g, '').replace(/<[^>]*>?/gm, '').trim();
2692
+ if (!cleanText) return resolve();
2693
+
2694
+ // Prevent overlapping audio protocols
2695
+ if (VoiceEngine.currentAudioNode) {
2696
+ VoiceEngine.currentAudioNode.pause();
2697
+ VoiceEngine.currentAudioNode = null;
2698
+ }
2699
+
2700
+ Utils.showToast("🔊 Connecting to Neural Voice Matrix (Gradio)...");
2701
 
2702
+ try {
2703
+ // Dynamically import Gradio Client from ESM CDN securely without breaking vanilla HTML environment
2704
+ const { Client } = await import('https://cdn.jsdelivr.net/npm/@gradio/client/+esm');
2705
+
2706
+ // Establish secure connection to HuggingFace Edge-TTS Space
2707
+ const client = await Client.connect("Vedika66/Edge-TTS");
2708
+
2709
+ // Dynamic Voice Type Assignment based on UI Smart Toggle
2710
+ const assignedVoice = VoiceEngine.currentLanguage === 'hi-IN'
2711
+ ? "प्रभात (भारी और प्राकृतिक आवाज़ - हिंग्लिश के लिए)"
2712
+ : "Christopher (Professional and Natural - US English)";
2713
+
2714
+ // Execute prediction protocol
2715
+ const result = await client.predict("/smart_hybrid_tts", {
2716
+ text: cleanText,
2717
+ voice_type: assignedVoice,
2718
+ });
2719
+
2720
+ if (result && result.data && result.data.length > 0) {
2721
+ const audioResponseData = result.data;
2722
+
2723
+ // Gradio returns object with URL in modern iterations, or fallback to direct string
2724
+ const targetAudioUrl = typeof audioResponseData === 'object' && audioResponseData !== null
2725
+ ? audioResponseData.url
2726
+ : audioResponseData;
2727
+
2728
+ const playbackAudio = new Audio(targetAudioUrl);
2729
+ VoiceEngine.currentAudioNode = playbackAudio;
2730
+
2731
+ playbackAudio.onplay = () => {
2732
+ if (AppState.isLiveModeEngaged) {
2733
+ document.getElementById('liveStatusText').innerText = "Arjun Transmitting...";
2734
+ } else {
2735
+ Utils.showToast("🔊 Neural audio playback active...");
2736
+ }
2737
+ };
2738
+
2739
+ // Critical: Resolve promise ONLY when audio naturally concludes
2740
+ playbackAudio.onended = () => {
2741
+ VoiceEngine.currentAudioNode = null;
2742
+ if (AppState.isLiveModeEngaged) {
2743
+ document.getElementById('liveStatusText').innerText = "Tap mic to respond";
2744
+ }
2745
+ resolve();
2746
+ };
2747
+
2748
+ playbackAudio.onerror = () => {
2749
+ Utils.showToast("Audio playback stream encountered an anomaly.");
2750
+ resolve();
2751
+ }
2752
+
2753
+ await playbackAudio.play();
2754
+
2755
+ } else {
2756
+ throw new Error("Invalid TTS Matrix Output");
2757
+ }
2758
+ } catch (error) {
2759
+ console.error("Gradio TTS Synthesis Error:", error);
2760
+ Utils.showToast("Neural link failed. Verify Gradio Edge-TTS availability.");
2761
+ if (AppState.isLiveModeEngaged) {
2762
+ document.getElementById('liveStatusText').innerText = "Acoustic Module Offline.";
2763
+ }
2764
+ resolve(); // Resolve to prevent promise hanging
2765
+ }
2766
+ });
2767
  }
2768
  };
2769
  VoiceEngine.init();
 
2784
  terminate: () => {
2785
  AppState.isLiveModeEngaged = false;
2786
  document.getElementById('liveOverlay').classList.remove('active');
2787
+
2788
+ // Halt audio if speaking during exit
2789
+ if (VoiceEngine.currentAudioNode) {
2790
+ VoiceEngine.currentAudioNode.pause();
2791
+ VoiceEngine.currentAudioNode = null;
2792
+ }
2793
+
2794
  if (VoiceEngine.recognition) {
2795
  try { VoiceEngine.recognition.stop(); } catch(e){}
2796
  }
 
2807
  },
2808
 
2809
  processFile: async (inputElement, typeContext) => {
2810
+ const file = inputElement.files;
2811
  if (!file) return;
2812
 
2813
  const fName = file.name.toLowerCase();
 
2834
 
2835
  if (typeContext === 'image') {
2836
  fileReader.onload = (e) => {
2837
+ AppState.pendingAttachment = { type: 'image', data: e.target.result.split(','), name: file.name };
2838
  thumbImg.src = e.target.result;
2839
  thumbImg.style.display = 'flex';
2840
  };
 
2842
  }
2843
  else if (typeContext === 'video' || typeContext === 'audio') {
2844
  fileReader.onload = (e) => {
2845
+ AppState.pendingAttachment = { type: typeContext, data: e.target.result.split(','), name: file.name };
2846
  docIcon.innerText = typeContext === 'video' ? '🎥' : '🎵';
2847
  docIcon.style.display = 'flex';
2848
  };
 
2942
  const MD_Renderer = new marked.Renderer();
2943
  MD_Renderer.code = function(token) {
2944
  const rawCode = typeof token === 'string' ? token : (token.text || '');
2945
+ const langClass = typeof token === 'string' ? arguments : (token.lang || '');
2946
 
2947
  // Render beautiful loading box during stream
2948
  if (AppState.isStreamingActive) {
 
3006
  syncHistoryFromCloud: async () => {
3007
  const messageZone = document.getElementById('msgs');
3008
  document.getElementById('welcomeState').style.display = 'none';
3009
+ messageZone.innerHTML = '<div style="text-align:center; padding:80px; font-weight:800; color:var(--text-tertiary); font-size:18px;">Decrypting Historic Archives...</div>';
3010
 
3011
  try {
3012
  const response = await fetch(Config.GAS_URL, {
 
3060
  },
3061
 
3062
  renderUserMessage: (textContent, badgeText, previewHTMLString = '') => {
3063
+ let badgeNode = badgeText ? `<div style="font-size:11px;font-weight:700;color:var(--brand-saffron);margin-bottom:6px;">${Utils.escapeHTML(badgeText)}</div>` : '';
3064
  const bubbleBox = document.createElement('div');
3065
  bubbleBox.className = 'chat-message-row user-msg';
3066
  bubbleBox.innerHTML = `
 
3223
  attachments: payloadAttachments,
3224
  system_prompt: cognitivePrompt,
3225
  history: secureHistory,
3226
+ max_tokens: AppState.isLiveModeEngaged ? 150 : 4096,
3227
  temperature: 0.75
3228
  };
3229
 
 
3257
 
3258
  try {
3259
  const jsonSegment = JSON.parse(parseableStr);
3260
+ if (jsonSegment.choices && jsonSegment.choices.delta.content) {
3261
+ responseBuffer += jsonSegment.choices.delta.content;
3262
  ChatEngine.updateBotBubble(activeBotBubble, responseBuffer, true);
3263
  UIManager.autoScroll();
3264
  }
 
3273
  ChatEngine.saveHistoryToCloud();
3274
 
3275
  if (AppState.isLiveModeEngaged) {
3276
+ document.getElementById('liveStatusText').innerText = "Synthesizing Audio...";
3277
+ // Wait for TTS to finish speaking entirely
3278
  await VoiceEngine.executeTTS(responseBuffer);
 
3279
  }
3280
 
3281
  } catch(error) {
 
3299
 
3300
  </script>
3301
  </body>
3302
+ </html>