@@ -49,6 +49,7 @@ async def run_browser_agent(
49
49
window_w ,
50
50
window_h ,
51
51
save_recording_path ,
52
+ save_trace_path ,
52
53
enable_recording ,
53
54
task ,
54
55
add_infos ,
@@ -89,6 +90,7 @@ async def run_browser_agent(
89
90
window_w = window_w ,
90
91
window_h = window_h ,
91
92
save_recording_path = save_recording_path ,
93
+ save_trace_path = save_trace_path ,
92
94
task = task ,
93
95
max_steps = max_steps ,
94
96
use_vision = use_vision ,
@@ -104,6 +106,7 @@ async def run_browser_agent(
104
106
window_w = window_w ,
105
107
window_h = window_h ,
106
108
save_recording_path = save_recording_path ,
109
+ save_trace_path = save_trace_path ,
107
110
task = task ,
108
111
add_infos = add_infos ,
109
112
max_steps = max_steps ,
@@ -134,6 +137,7 @@ async def run_org_agent(
134
137
window_w ,
135
138
window_h ,
136
139
save_recording_path ,
140
+ save_trace_path ,
137
141
task ,
138
142
max_steps ,
139
143
use_vision ,
@@ -150,7 +154,7 @@ async def run_org_agent(
150
154
)
151
155
async with await browser .new_context (
152
156
config = BrowserContextConfig (
153
- trace_path = "./tmp/traces" ,
157
+ trace_path = save_trace_path if save_trace_path else None ,
154
158
save_recording_path = save_recording_path if save_recording_path else None ,
155
159
no_viewport = False ,
156
160
browser_window_size = BrowserContextWindowSize (
@@ -184,6 +188,7 @@ async def run_custom_agent(
184
188
window_w ,
185
189
window_h ,
186
190
save_recording_path ,
191
+ save_trace_path ,
187
192
task ,
188
193
add_infos ,
189
194
max_steps ,
@@ -204,7 +209,7 @@ async def run_custom_agent(
204
209
chrome_exe = None
205
210
elif not os .path .exists (chrome_exe ):
206
211
raise ValueError (f"Chrome executable not found at { chrome_exe } " )
207
-
212
+
208
213
if chrome_use_data == "" :
209
214
chrome_use_data = None
210
215
@@ -235,7 +240,7 @@ async def run_custom_agent(
235
240
)
236
241
async with await browser .new_context (
237
242
config = BrowserContextConfig (
238
- trace_path = "./tmp/result_processing" ,
243
+ trace_path = save_trace_path if save_trace_path else None ,
239
244
save_recording_path = save_recording_path
240
245
if save_recording_path
241
246
else None ,
@@ -407,7 +412,7 @@ def create_ui(theme_name="Ocean"):
407
412
value = os .getenv (f"{ llm_provider .value .upper ()} _API_KEY" , "" ), # Default to .env value
408
413
info = "Your API key (leave blank to use .env)"
409
414
)
410
-
415
+
411
416
with gr .TabItem ("🌐 Browser Settings" , id = 3 ):
412
417
with gr .Group ():
413
418
with gr .Row ():
@@ -452,6 +457,14 @@ def create_ui(theme_name="Ocean"):
452
457
interactive = True , # Allow editing only if recording is enabled
453
458
)
454
459
460
+ save_trace_path = gr .Textbox (
461
+ label = "Trace Path" ,
462
+ placeholder = "e.g. ./tmp/traces" ,
463
+ value = "./tmp/traces" ,
464
+ info = "Path to save Agent traces" ,
465
+ interactive = True ,
466
+ )
467
+
455
468
with gr .TabItem ("🤖 Run Agent" , id = 4 ):
456
469
task = gr .Textbox (
457
470
label = "Task Description" ,
@@ -494,24 +507,24 @@ def create_ui(theme_name="Ocean"):
494
507
model_thoughts_output = gr .Textbox (
495
508
label = "Model Thoughts" , lines = 3 , show_label = True
496
509
)
497
-
510
+
498
511
with gr .TabItem ("🎥 Recordings" , id = 6 ):
499
512
def list_recordings (save_recording_path ):
500
513
if not os .path .exists (save_recording_path ):
501
514
return []
502
-
515
+
503
516
# Get all video files
504
517
recordings = glob .glob (os .path .join (save_recording_path , "*.[mM][pP]4" )) + glob .glob (os .path .join (save_recording_path , "*.[wW][eE][bB][mM]" ))
505
-
518
+
506
519
# Sort recordings by creation time (oldest first)
507
520
recordings .sort (key = os .path .getctime )
508
-
521
+
509
522
# Add numbering to the recordings
510
523
numbered_recordings = []
511
524
for idx , recording in enumerate (recordings , start = 1 ):
512
525
filename = os .path .basename (recording )
513
526
numbered_recordings .append ((recording , f"{ idx } . { filename } " ))
514
-
527
+
515
528
return numbered_recordings
516
529
517
530
recordings_gallery = gr .Gallery (
@@ -534,21 +547,21 @@ def list_recordings(save_recording_path):
534
547
lambda provider , api_key , base_url : update_model_dropdown (provider , api_key , base_url ),
535
548
inputs = [llm_provider , llm_api_key , llm_base_url ],
536
549
outputs = llm_model_name
537
- )
550
+ )
538
551
539
552
# Add this after defining the components
540
553
enable_recording .change (
541
554
lambda enabled : gr .update (interactive = enabled ),
542
555
inputs = enable_recording ,
543
556
outputs = save_recording_path
544
557
)
545
-
558
+
546
559
# Run button click handler
547
560
run_button .click (
548
561
fn = run_browser_agent ,
549
562
inputs = [
550
563
agent_type , llm_provider , llm_model_name , llm_temperature , llm_base_url , llm_api_key ,
551
- use_own_browser , headless , disable_security , window_w , window_h , save_recording_path ,
564
+ use_own_browser , headless , disable_security , window_w , window_h , save_recording_path , save_trace_path ,
552
565
enable_recording , task , add_infos , max_steps , use_vision , max_actions_per_step , tool_call_in_content
553
566
],
554
567
outputs = [final_result_output , errors_output , model_actions_output , model_thoughts_output , recording_display ],
0 commit comments