| import os | |
| import socket | |
| import subprocess | |
| import argparse | |
| import gradio as gr | |
| from src.webui.interface import theme_map, create_ui | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| html=""" | |
| <div id="vnc-container" style="width:100%;height:800px;border:2px solid #444;border-radius:8px;"></div> | |
| <script type="module"> | |
| import RFB from "https://unpkg.com/@novnc/novnc/core/rfb.js"; | |
| // Connect directly to your WebSocket proxy | |
| const url = "ws://localhost:6080/websockify"; | |
| const target = document.getElementById('vnc-container'); | |
| try { | |
| const rfb = new RFB(target, url); | |
| rfb.viewOnly = false; // true = disable keyboard/mouse input | |
| rfb.scaleViewport = true; | |
| rfb.resizeSession = true; | |
| rfb.background = "black"; | |
| console.log("โ Connected to VNC via WebSocket:", url); | |
| } catch (err) { | |
| target.innerHTML = "<p style='color:red'> โ Failed to connect to VNC server.<br>" + err + "</p>"; | |
| } | |
| </script> | |
| """ | |
| def get_vnc_iframe(): | |
| # get hostname + IP | |
| hostname = socket.gethostname() | |
| ip = socket.gethostbyname(hostname) | |
| hostname = subprocess.check_output("hostname", shell=True).decode().strip() | |
| # build iframe URL | |
| url_old = f"http://{hostname}:6080/vnc.html?host={hostname}&port=6080" | |
| url=f"/usr/share/novnc/vnc.html?host={hostname}&port=6080" | |
| print("############## URL :",url) | |
| # return HTML iframe | |
| return f""" | |
| <iframe src="{url}" width="100%" height="800" style="border:1px solid red;"></iframe> | |
| """ | |
| # # Example theme map for the argument parser (add more themes if you have them) | |
| # theme_map = { | |
| # "Ocean": gr.themes.Ocean(), | |
| # "Default": gr.themes.Default(), | |
| # # Add other themes as needed | |
| # } | |
| # # Function to run VNC setup (generates .vnc/passwd) | |
| # def setup_vnc(password): | |
| # vnc_dir = os.path.expanduser("~/.vnc") | |
| # os.makedirs(vnc_dir, exist_ok=True) | |
| # passwd_file = os.path.join(vnc_dir, "passwd") | |
| # proc = subprocess.Popen( | |
| # f"echo '{password}' | vncpasswd -f > '{passwd_file}'", | |
| # shell=True, | |
| # stdout=subprocess.PIPE, | |
| # stderr=subprocess.PIPE, | |
| # ) | |
| # stdout, stderr = proc.communicate() | |
| # os.chmod(passwd_file, 0o600) | |
| # return f"VNC password set to: {password}\n{stdout.decode()}\n{stderr.decode()}" | |
| # # Function to run the webui.py application | |
| # def start_webui(ip="0.0.0.0", port=7860): | |
| # # This will run in a thread | |
| # def run(): | |
| # subprocess.run(["python", "webui.py", "--ip", ip, "--port", str(port)], cwd="/app") | |
| # thread = threading.Thread(target=run, daemon=True) | |
| # thread.start() | |
| # return f"webui.py started at http://{ip}:{port}" | |
| # # Gradio interface for VNC setup | |
| # def vnc_setup(password): | |
| # result = setup_vnc(password) | |
| # return result | |
| # # Main app UI (tab content) | |
| # def create_ui(theme_name="Ocean"): | |
| # with gr.Blocks(theme=theme_map.get(theme_name, gr.themes.Ocean())) as base_ui: | |
| # gr.Markdown("## WebUI and VNC Setup") | |
| # with gr.Tab("Start WebUI"): | |
| # with gr.Row(): | |
| # ip = gr.Textbox(label="IP", value="0.0.0.0") | |
| # port = gr.Number(label="Port", value=7788) | |
| # webui_btn = gr.Button("Start WebUI") | |
| # webui_out = gr.Textbox(label="WebUI Output") | |
| # webui_btn.click(start_webui, inputs=[ip, port], outputs=webui_out) | |
| # with gr.Tab("VNC Setup"): | |
| # vnc_password = gr.Textbox(label="VNC Password", type="password") | |
| # vnc_btn = gr.Button("Setup VNC Password") | |
| # vnc_out = gr.Textbox(label="VNC Setup Output") | |
| # vnc_btn.click(vnc_setup, inputs=[vnc_password], outputs=vnc_out) | |
| # return base_ui | |
| def main(): | |
| parser = argparse.ArgumentParser(description="Gradio WebUI for Browser Agent") | |
| parser.add_argument("--ip", type=str, default=os.getenv("HOST", "0.0.0.0"), help="IP address to bind to") | |
| parser.add_argument("--port", type=int, default=int(os.getenv("PORT", "7860")), help="Port to listen on") | |
| parser.add_argument("--theme", type=str, default=os.getenv("THEME", "Ocean"), choices=theme_map.keys(), help="Theme to use for the UI") | |
| args = parser.parse_args() | |
| # Existing UI | |
| base_ui = create_ui(theme_name=args.theme) | |
| # Combine into single Gradio app | |
| with gr.Blocks(theme=theme_map[args.theme]) as demo: | |
| gr.Markdown("# ๐ Browser Agent Web-UI") | |
| with gr.Tab("Main App"): | |
| base_ui.render() | |
| with gr.Tab("Web VNC"): | |
| # The iframe must point to the actual noVNC server (default: localhost:6080/vnc.html) | |
| # gr.HTML(f'<iframe src="http://localhost:6080/vnc.html" width="100%" height="800" style="border:1px solid red;"></iframe>') | |
| # gr.HTML(html) | |
| gr.HTML(get_vnc_iframe()) | |
| demo.queue().launch(server_name=args.ip, server_port=args.port) | |
| if __name__ == "__main__": | |
| main() |