@@ -54,8 +54,14 @@ async def run_browser_agent(
54
54
max_steps ,
55
55
use_vision
56
56
):
57
+ # Ensure the recording directory exists
58
+ os .makedirs (save_recording_path , exist_ok = True )
57
59
60
+ # Get the list of existing videos before the agent runs
61
+ existing_videos = set (glob .glob (os .path .join (save_recording_path , '*.[mM][pP]4' )) +
62
+ glob .glob (os .path .join (save_recording_path , '*.[wW][eE][bB][mM]' )))
58
63
64
+ # Run the agent
59
65
llm = utils .get_llm_model (
60
66
provider = llm_provider ,
61
67
model_name = llm_model_name ,
@@ -64,7 +70,7 @@ async def run_browser_agent(
64
70
api_key = llm_api_key
65
71
)
66
72
if agent_type == "org" :
67
- return await run_org_agent (
73
+ final_result , errors , model_actions , model_thoughts = await run_org_agent (
68
74
llm = llm ,
69
75
headless = headless ,
70
76
disable_security = disable_security ,
@@ -76,7 +82,7 @@ async def run_browser_agent(
76
82
use_vision = use_vision
77
83
)
78
84
elif agent_type == "custom" :
79
- return await run_custom_agent (
85
+ final_result , errors , model_actions , model_thoughts = await run_custom_agent (
80
86
llm = llm ,
81
87
use_own_browser = use_own_browser ,
82
88
headless = headless ,
@@ -92,6 +98,17 @@ async def run_browser_agent(
92
98
else :
93
99
raise ValueError (f"Invalid agent type: { agent_type } " )
94
100
101
+ # Get the list of videos after the agent runs
102
+ new_videos = set (glob .glob (os .path .join (save_recording_path , '*.[mM][pP]4' )) +
103
+ glob .glob (os .path .join (save_recording_path , '*.[wW][eE][bB][mM]' )))
104
+
105
+ # Find the newly created video
106
+ latest_video = None
107
+ if new_videos - existing_videos :
108
+ latest_video = list (new_videos - existing_videos )[0 ] # Get the first new video
109
+
110
+ return final_result , errors , model_actions , model_thoughts , latest_video
111
+
95
112
async def run_org_agent (
96
113
llm ,
97
114
headless ,
@@ -222,6 +239,7 @@ async def run_custom_agent(
222
239
await browser .close ()
223
240
return final_result , errors , model_actions , model_thoughts
224
241
242
+
225
243
import argparse
226
244
import gradio as gr
227
245
from gradio .themes import Base , Default , Soft , Monochrome , Glass , Origin , Citrus , Ocean
@@ -239,8 +257,6 @@ async def run_custom_agent(
239
257
}
240
258
241
259
def create_ui (theme_name = "Ocean" ):
242
- """Create the UI with the specified theme"""
243
- # Enhanced styling for better visual appeal
244
260
css = """
245
261
.gradio-container {
246
262
max-width: 1200px !important;
@@ -257,8 +273,18 @@ def create_ui(theme_name="Ocean"):
257
273
border-radius: 10px;
258
274
}
259
275
"""
276
+
277
+ js = """
278
+ function refresh() {
279
+ const url = new URL(window.location);
280
+ if (url.searchParams.get('__theme') !== 'dark') {
281
+ url.searchParams.set('__theme', 'dark');
282
+ window.location.href = url.href;
283
+ }
284
+ }
285
+ """
260
286
261
- with gr .Blocks (title = "Browser Use WebUI" , theme = theme_map [theme_name ], css = css ) as demo :
287
+ with gr .Blocks (title = "Browser Use WebUI" , theme = theme_map [theme_name ], css = css , js = js ) as demo :
262
288
with gr .Row ():
263
289
gr .Markdown (
264
290
"""
@@ -294,7 +320,7 @@ def create_ui(theme_name="Ocean"):
294
320
with gr .TabItem ("🔧 LLM Configuration" , id = 2 ):
295
321
with gr .Group ():
296
322
llm_provider = gr .Dropdown (
297
- ["anthropic" , "openai" , "gemini" , "azure_openai" , "deepseek" , "ollama" ],
323
+ ["anthropic" , "openai" , "gemini" , "azure_openai" , "deepseek" ],
298
324
label = "LLM Provider" ,
299
325
value = "gemini" ,
300
326
info = "Select your preferred language model provider"
@@ -381,34 +407,7 @@ def create_ui(theme_name="Ocean"):
381
407
stop_button = gr .Button ("⏹️ Stop" , variant = "stop" , scale = 1 )
382
408
383
409
with gr .TabItem ("🎬 Recordings" , id = 5 ):
384
- def list_videos (path ):
385
- """Return the latest video file from the specified path."""
386
- if not os .path .exists (path ):
387
- return ["Recording path not found" ]
388
-
389
- # Get all video files in the directory
390
- video_files = glob .glob (os .path .join (path , '*.[mM][pP]4' )) + glob .glob (os .path .join (path , '*.[wW][eE][bB][mM]' ))
391
-
392
- if not video_files :
393
- return ["No recordings found" ]
394
-
395
- # Sort files by modification time (latest first)
396
- video_files .sort (key = os .path .getmtime , reverse = True )
397
-
398
- # Return only the latest video
399
- return [video_files [0 ]]
400
-
401
- def display_videos (recording_path ):
402
- """Display the latest video in the gallery."""
403
- return list_videos (recording_path )
404
-
405
- recording_display = gr .Gallery (label = "Latest Recording" , type = "video" )
406
-
407
- demo .load (
408
- display_videos ,
409
- inputs = [save_recording_path ],
410
- outputs = [recording_display ]
411
- )
410
+ recording_display = gr .Video (label = "Latest Recording" )
412
411
413
412
with gr .Group ():
414
413
gr .Markdown ("### Results" )
@@ -448,7 +447,7 @@ def display_videos(recording_path):
448
447
disable_security , window_w , window_h , save_recording_path ,
449
448
task , add_infos , max_steps , use_vision
450
449
],
451
- outputs = [final_result_output , errors_output , model_actions_output , model_thoughts_output ]
450
+ outputs = [final_result_output , errors_output , model_actions_output , model_thoughts_output , recording_display ]
452
451
)
453
452
454
453
return demo
@@ -458,9 +457,9 @@ def main():
458
457
parser .add_argument ("--ip" , type = str , default = "127.0.0.1" , help = "IP address to bind to" )
459
458
parser .add_argument ("--port" , type = int , default = 7788 , help = "Port to listen on" )
460
459
parser .add_argument ("--theme" , type = str , default = "Ocean" , choices = theme_map .keys (), help = "Theme to use for the UI" )
460
+ parser .add_argument ("--dark-mode" , action = "store_true" , help = "Enable dark mode" )
461
461
args = parser .parse_args ()
462
462
463
- # Create the UI with the specified theme
464
463
demo = create_ui (theme_name = args .theme )
465
464
demo .launch (server_name = args .ip , server_port = args .port )
466
465
0 commit comments