| import gradio as gr |
| import requests |
| import os |
|
|
| JARVIS_API = os.getenv("JARVIS_API_URL", "https://jarvis-9vys.onrender.com") |
|
|
| def chat_with_jarvis(message, history): |
| if not message.strip(): |
| return history, "" |
| try: |
| res = requests.post(f"{JARVIS_API}/chat", json={ |
| "message": message, |
| "force_offline": False, |
| "text_only": False |
| }, timeout=60) |
| data = res.json() |
| response = data.get("response", "কোনো সাড়া পাওয়া যায়নি") |
| brain = data.get("brain_used", "Unknown") |
| mode = data.get("mode", "normal") |
| online = "🌐 Online" if data.get("online") else "📴 Offline" |
| reply = f"{response}\n\n---\n🧠 `{brain}` | {online} | Mode: `{mode}`" |
| except Exception as e: |
| reply = f"⚠️ JARVIS Server connect করা যাচ্ছে না।\n\n`Error: {str(e)}`" |
|
|
| history = history or [] |
| |
| history.append({"role": "user", "content": message}) |
| history.append({"role": "assistant", "content": reply}) |
| |
| return history, "" |
|
|
| def get_status(): |
| try: |
| res = requests.get(f"{JARVIS_API}/status", timeout=60) |
| data = res.json() |
| cpu = data["resource"]["cpu_percent"] |
| ram = data["resource"]["ram_percent"] |
| |
| |
| mem = data["memory"].get("supabase_total_memories", data["memory"].get("json_memory", 0)) |
| |
| idle = data["resource"]["idle_minutes"] |
| sleeping = data["resource"]["sleeping"] |
| status = "😴 SLEEP MODE" if sleeping else "⚡ ACTIVE" |
| |
| return f"◈ SYSTEM STATUS: **{status}** | 🖥️ CPU: **{cpu}%** | 💾 RAM: **{ram}%** | 🧠 MEMORIES: **{mem}** | ⏱️ IDLE: **{idle} min**" |
| |
| except Exception as e: |
| |
| return f"◈ SYSTEM STATUS: **⚠️ SERVER OFFLINE** — Error: {str(e)}" |
|
|
| custom_css = """ |
| @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Share+Tech+Mono&family=Exo+2:wght@300;400&display=swap'); |
| |
| *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } |
| |
| body { |
| background: #000510 !important; |
| font-family: 'Share Tech Mono', monospace !important; |
| overflow-x: hidden; |
| } |
| |
| /* Animated grid background */ |
| body::before { |
| content: ''; |
| position: fixed; |
| top: 0; left: 0; right: 0; bottom: 0; |
| background-image: |
| linear-gradient(rgba(0, 212, 255, 0.03) 1px, transparent 1px), |
| linear-gradient(90deg, rgba(0, 212, 255, 0.03) 1px, transparent 1px); |
| background-size: 50px 50px; |
| animation: gridMove 20s linear infinite; |
| pointer-events: none; |
| z-index: 0; |
| } |
| |
| /* Scanlines */ |
| body::after { |
| content: ''; |
| position: fixed; |
| top: 0; left: 0; right: 0; bottom: 0; |
| background: repeating-linear-gradient( |
| 0deg, |
| transparent, |
| transparent 2px, |
| rgba(0, 212, 255, 0.012) 2px, |
| rgba(0, 212, 255, 0.012) 4px |
| ); |
| pointer-events: none; |
| z-index: 1; |
| } |
| |
| @keyframes gridMove { |
| 0% { transform: translateY(0); } |
| 100% { transform: translateY(50px); } |
| } |
| |
| .gradio-container { |
| background: transparent !important; |
| max-width: 960px !important; |
| margin: 0 auto !important; |
| position: relative; |
| z-index: 2; |
| padding: 20px !important; |
| } |
| |
| /* ══ HEADER ══ */ |
| #jarvis-header { |
| text-align: center; |
| padding: 40px 0 10px; |
| position: relative; |
| } |
| |
| #jarvis-header::before { |
| content: ''; |
| position: absolute; |
| top: 50%; left: 50%; |
| transform: translate(-50%, -50%); |
| width: 400px; height: 400px; |
| background: radial-gradient(circle, rgba(0,100,255,0.08) 0%, transparent 70%); |
| pointer-events: none; |
| } |
| |
| #jarvis-logo { |
| font-family: 'Orbitron', monospace; |
| font-size: 4rem; |
| font-weight: 900; |
| background: linear-gradient(90deg, #00d4ff, #0066ff, #00ffcc, #00d4ff); |
| background-size: 300%; |
| -webkit-background-clip: text; |
| -webkit-text-fill-color: transparent; |
| background-clip: text; |
| animation: shimmer 4s linear infinite; |
| letter-spacing: 0.5em; |
| text-indent: 0.5em; |
| filter: drop-shadow(0 0 20px rgba(0, 212, 255, 0.4)); |
| } |
| |
| #jarvis-tagline { |
| font-family: 'Share Tech Mono', monospace; |
| font-size: 0.65rem; |
| color: rgba(0, 212, 255, 0.4); |
| letter-spacing: 0.6em; |
| text-transform: uppercase; |
| margin-top: 4px; |
| text-indent: 0.6em; |
| } |
| |
| #jarvis-divider { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| margin: 20px 0; |
| opacity: 0.4; |
| } |
| |
| #jarvis-divider::before, #jarvis-divider::after { |
| content: ''; |
| flex: 1; |
| height: 1px; |
| background: linear-gradient(90deg, transparent, #00d4ff, transparent); |
| } |
| |
| #jarvis-divider span { |
| font-family: 'Orbitron', monospace; |
| font-size: 0.5rem; |
| color: #00d4ff; |
| letter-spacing: 0.3em; |
| } |
| |
| @keyframes shimmer { |
| 0% { background-position: 0% } |
| 100% { background-position: 300% } |
| } |
| |
| /* ══ STATUS BAR ══ */ |
| #status-bar { |
| background: rgba(0, 20, 50, 0.6) !important; |
| border: 1px solid rgba(0, 212, 255, 0.2) !important; |
| border-radius: 6px !important; |
| padding: 10px 20px !important; |
| margin-bottom: 16px !important; |
| font-family: 'Share Tech Mono', monospace !important; |
| font-size: 0.72rem !important; |
| color: rgba(0, 212, 255, 0.6) !important; |
| text-align: center; |
| letter-spacing: 0.05em; |
| position: relative; |
| overflow: hidden; |
| } |
| |
| #status-bar::before { |
| content: ''; |
| position: absolute; |
| top: 0; left: -100%; |
| width: 60%; height: 100%; |
| background: linear-gradient(90deg, transparent, rgba(0,212,255,0.05), transparent); |
| animation: scan 4s linear infinite; |
| } |
| |
| @keyframes scan { |
| 0% { left: -60%; } |
| 100% { left: 160%; } |
| } |
| |
| /* ══ CHAT WINDOW ══ */ |
| .chat-wrap { |
| background: rgba(0, 10, 30, 0.85) !important; |
| border: 1px solid rgba(0, 212, 255, 0.2) !important; |
| border-radius: 12px !important; |
| overflow: hidden !important; |
| box-shadow: |
| 0 0 40px rgba(0, 212, 255, 0.08), |
| 0 0 80px rgba(0, 50, 200, 0.06), |
| inset 0 0 40px rgba(0, 0, 20, 0.5) !important; |
| position: relative; |
| } |
| |
| .chat-wrap::before { |
| content: 'NEURAL INTERFACE'; |
| position: absolute; |
| top: 10px; right: 16px; |
| font-family: 'Orbitron', monospace; |
| font-size: 0.45rem; |
| color: rgba(0,212,255,0.2); |
| letter-spacing: 0.3em; |
| z-index: 10; |
| } |
| |
| /* Messages */ |
| .message { |
| font-family: 'Share Tech Mono', monospace !important; |
| font-size: 0.88rem !important; |
| line-height: 1.6 !important; |
| border-radius: 8px !important; |
| padding: 12px 16px !important; |
| } |
| |
| .message.user { |
| background: rgba(0, 80, 200, 0.12) !important; |
| border: 1px solid rgba(0, 100, 255, 0.25) !important; |
| color: rgba(160, 210, 255, 0.9) !important; |
| } |
| |
| .message.bot, .message.assistant { |
| background: rgba(0, 212, 255, 0.06) !important; |
| border: 1px solid rgba(0, 212, 255, 0.2) !important; |
| color: rgba(220, 245, 255, 0.9) !important; |
| } |
| |
| /* ══ INPUT AREA ══ */ |
| textarea, input[type="text"] { |
| background: rgba(0, 8, 24, 0.95) !important; |
| border: 1px solid rgba(0, 212, 255, 0.3) !important; |
| border-radius: 8px !important; |
| color: #00d4ff !important; |
| font-family: 'Share Tech Mono', monospace !important; |
| font-size: 0.9rem !important; |
| caret-color: #00d4ff !important; |
| transition: all 0.3s !important; |
| padding: 12px 16px !important; |
| } |
| |
| textarea:focus, input[type="text"]:focus { |
| border-color: rgba(0, 212, 255, 0.8) !important; |
| box-shadow: 0 0 20px rgba(0, 212, 255, 0.2), inset 0 0 10px rgba(0,212,255,0.03) !important; |
| outline: none !important; |
| } |
| |
| textarea::placeholder { color: rgba(0, 212, 255, 0.25) !important; } |
| |
| /* ══ BUTTONS ══ */ |
| button { |
| font-family: 'Orbitron', monospace !important; |
| letter-spacing: 0.15em !important; |
| font-size: 0.65rem !important; |
| border-radius: 6px !important; |
| transition: all 0.3s ease !important; |
| text-transform: uppercase !important; |
| } |
| |
| button.primary { |
| background: transparent !important; |
| border: 1px solid rgba(0, 212, 255, 0.8) !important; |
| color: #00d4ff !important; |
| padding: 10px 20px !important; |
| } |
| |
| button.primary:hover { |
| background: rgba(0, 212, 255, 0.1) !important; |
| box-shadow: 0 0 25px rgba(0, 212, 255, 0.3), inset 0 0 15px rgba(0,212,255,0.05) !important; |
| border-color: #00d4ff !important; |
| } |
| |
| button.secondary { |
| background: transparent !important; |
| border: 1px solid rgba(0, 100, 255, 0.4) !important; |
| color: rgba(80, 150, 255, 0.8) !important; |
| } |
| |
| button.secondary:hover { |
| background: rgba(0, 80, 200, 0.1) !important; |
| border-color: rgba(0, 150, 255, 0.7) !important; |
| box-shadow: 0 0 15px rgba(0, 100, 255, 0.2) !important; |
| } |
| |
| /* ══ LABELS ══ */ |
| label, .label-wrap span { |
| font-family: 'Share Tech Mono', monospace !important; |
| font-size: 0.65rem !important; |
| color: rgba(0, 212, 255, 0.35) !important; |
| letter-spacing: 0.25em !important; |
| text-transform: uppercase !important; |
| } |
| |
| /* ══ SCROLLBAR ══ */ |
| ::-webkit-scrollbar { width: 3px; height: 3px; } |
| ::-webkit-scrollbar-track { background: rgba(0,5,16,0.5); } |
| ::-webkit-scrollbar-thumb { |
| background: linear-gradient(180deg, #00d4ff44, #0066ff44); |
| border-radius: 2px; |
| } |
| |
| /* ══ CORNER DECORATIONS ══ */ |
| #corner-tl, #corner-tr, #corner-bl, #corner-br { |
| position: absolute; |
| width: 20px; height: 20px; |
| pointer-events: none; |
| opacity: 0.5; |
| } |
| #corner-tl { top: 0; left: 0; border-top: 1px solid #00d4ff; border-left: 1px solid #00d4ff; } |
| #corner-tr { top: 0; right: 0; border-top: 1px solid #00d4ff; border-right: 1px solid #00d4ff; } |
| #corner-bl { bottom: 0; left: 0; border-bottom: 1px solid #00d4ff; border-left: 1px solid #00d4ff; } |
| #corner-br { bottom: 0; right: 0; border-bottom: 1px solid #00d4ff; border-right: 1px solid #00d4ff; } |
| """ |
|
|
| |
| with gr.Blocks(title="J.A.R.V.I.S — AI System") as demo: |
|
|
| gr.HTML(""" |
| <div id="jarvis-header"> |
| <div id="jarvis-logo">JARVIS</div> |
| <div id="jarvis-tagline">Just A Rather Very Intelligent System</div> |
| </div> |
| <div id="jarvis-divider"><span>◈ NEURAL LINK ESTABLISHED ◈</span></div> |
| """) |
|
|
| status_bar = gr.Markdown("◈ Connecting to JARVIS core...", elem_id="status-bar") |
|
|
| with gr.Column(elem_classes="chat-wrap"): |
| gr.HTML('<div id="corner-tl"></div><div id="corner-tr"></div><div id="corner-bl"></div><div id="corner-br"></div>') |
| |
| chatbot = gr.Chatbot( |
| label="NEURAL INTERFACE", |
| height=480, |
| show_label=False |
| ) |
|
|
| with gr.Row(): |
| msg_input = gr.Textbox( |
| placeholder="▸ Command input — JARVIS-কে যা বলতে চাও লেখো...", |
| show_label=False, |
| scale=6, |
| container=False, |
| lines=1 |
| ) |
| send_btn = gr.Button("⚡ EXECUTE", variant="primary", scale=1) |
| clear_btn = gr.Button("⊘ CLEAR", variant="secondary", scale=1) |
|
|
| gr.HTML(""" |
| <div style="text-align:center; margin-top:16px; font-family:'Share Tech Mono',monospace; |
| font-size:0.6rem; color:rgba(0,212,255,0.2); letter-spacing:0.3em;"> |
| ◈ JARVIS AI SYSTEM v1.0 | MULTI-BRAIN ENGINE | ENCRYPTED CHANNEL ◈ |
| </div> |
| """) |
|
|
| send_btn.click(chat_with_jarvis, inputs=[msg_input, chatbot], outputs=[chatbot, msg_input]) |
| msg_input.submit(chat_with_jarvis, inputs=[msg_input, chatbot], outputs=[chatbot, msg_input]) |
| clear_btn.click(lambda: ([], ""), outputs=[chatbot, msg_input]) |
| |
| demo.load(get_status, outputs=status_bar) |
| timer = gr.Timer(30) |
| timer.tick(get_status, outputs=status_bar) |
|
|
| |
| if __name__ == "__main__": |
| demo.launch(css=custom_css) |
|
|