Skip to content

Commit 0d259ef

Browse files
committed
add load and save config tab
1 parent 6ac9e26 commit 0d259ef

File tree

6 files changed

+154
-15
lines changed

6 files changed

+154
-15
lines changed

src/webui/components/agent_settings_tab.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ def update_mcp_server(mcp_file: str):
2727
"""
2828
Update the MCP server.
2929
"""
30-
if not mcp_file or not os.path.exists(mcp_file) or mcp_file.endswith('.json'):
30+
if not mcp_file or not os.path.exists(mcp_file) or not mcp_file.endswith('.json'):
3131
logger.warning(f"{mcp_file} is not a valid MCP file.")
32-
return gr.update()
32+
return None, gr.update(visible=False)
3333

3434
with open(mcp_file, 'r') as f:
3535
mcp_server = json.load(f)
3636

37-
return gr.update(value=json.dumps(mcp_server, indent=2), visible=True)
37+
return json.dumps(mcp_server, indent=2), gr.update(visible=True)
3838

3939

4040
def create_agent_settings_tab(webui_manager: WebuiManager) -> dict[str, Component]:
@@ -50,7 +50,7 @@ def create_agent_settings_tab(webui_manager: WebuiManager) -> dict[str, Componen
5050
extend_system_prompt = gr.Textbox(label="Extend system prompt", lines=4, interactive=True)
5151

5252
with gr.Group():
53-
mcp_json_file = gr.File(label="MCP server file", interactive=True, file_types=["json"])
53+
mcp_json_file = gr.File(label="MCP server file", interactive=True, file_types=[".json"])
5454
mcp_server_config = gr.Textbox(label="MCP server", lines=6, interactive=True, visible=False)
5555

5656
with gr.Group():
@@ -202,7 +202,7 @@ def create_agent_settings_tab(webui_manager: WebuiManager) -> dict[str, Componen
202202
allow_custom_value=True,
203203
choices=["auto", "json_schema", "function_calling", "None"],
204204
info="Tool Calls Function Name",
205-
visible=False
205+
visible=True
206206
)
207207
tab_components.update(dict(
208208
override_system_prompt=override_system_prompt,
@@ -252,7 +252,7 @@ def create_agent_settings_tab(webui_manager: WebuiManager) -> dict[str, Componen
252252
mcp_json_file.change(
253253
update_mcp_server,
254254
inputs=mcp_json_file,
255-
outputs=mcp_server_config
255+
outputs=[mcp_server_config, mcp_server_config]
256256
)
257257

258258
return tab_components

src/webui/components/browser_use_agent_tab.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def create_browser_use_agent_tab(webui_manager: WebuiManager) -> dict[str, Compo
2222

2323
with gr.Row():
2424
stop_button = gr.Button("⏹️ Stop", interactive=False, variant="stop", scale=2)
25-
clear_button = gr.Button("🧹 Clear", interactive=False, variant="stop", scale=2)
25+
clear_button = gr.Button("🧹 Clear", interactive=True, variant="stop", scale=2)
2626
run_button = gr.Button("▶️ Summit", variant="primary", scale=3)
2727

2828
browser_view = gr.HTML(
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import gradio as gr
2+
from gradio.components import Component
3+
4+
from src.webui.webui_manager import WebuiManager
5+
from src.utils import config
6+
7+
8+
def create_deep_research_agent_tab(webui_manager: WebuiManager) -> dict[str, Component]:
9+
"""
10+
Creates a deep research agent tab
11+
"""
12+
input_components = set(webui_manager.get_components())
13+
tab_components = {}
14+
15+
research_task = gr.Textbox(label="Research Task", lines=5,
16+
value="Give me a detailed plan for traveling to Switzerland on June 1st.",
17+
interactive=True)
18+
with gr.Row():
19+
max_iteration = gr.Number(label="Max Search Iteration", value=3,
20+
precision=0,
21+
interactive=True) # precision=0 确保是整数
22+
max_query = gr.Number(label="Max Query per Iteration", value=1,
23+
precision=0,
24+
interactive=True) # precision=0 确保是整数
25+
with gr.Row():
26+
stop_button = gr.Button("⏹️ Stop", variant="stop", scale=2)
27+
start_button = gr.Button("▶️ Run", variant="primary", scale=3)
28+
markdown_display = gr.Markdown(label="Research Report")
29+
markdown_download = gr.File(label="Download Research Report", interactive=False)
30+
tab_components.update(
31+
dict(
32+
research_task=research_task,
33+
max_iteration=max_iteration,
34+
max_query=max_query,
35+
start_button=start_button,
36+
stop_button=stop_button,
37+
markdown_display=markdown_display,
38+
markdown_download=markdown_download,
39+
)
40+
)
41+
return tab_components
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import gradio as gr
2+
from gradio.components import Component
3+
4+
from src.webui.webui_manager import WebuiManager
5+
from src.utils import config
6+
7+
8+
def create_load_save_config_tab(webui_manager: WebuiManager) -> dict[str, Component]:
9+
"""
10+
Creates a load and save config tab.
11+
"""
12+
input_components = set(webui_manager.get_components())
13+
tab_components = {}
14+
15+
config_file = gr.File(
16+
label="Load UI Settings from Config File",
17+
file_types=[".json"],
18+
interactive=True
19+
)
20+
with gr.Row():
21+
load_config_button = gr.Button("Load Config", variant="primary")
22+
save_config_button = gr.Button("Save UI Settings", variant="primary")
23+
24+
config_status = gr.Textbox(
25+
label="Status",
26+
lines=2,
27+
interactive=False
28+
)
29+
30+
tab_components.update(dict(
31+
load_config_button=load_config_button,
32+
save_config_button=save_config_button,
33+
config_status=config_status,
34+
config_file=config_file,
35+
))
36+
37+
save_config_button.click(
38+
fn=webui_manager.save_current_config,
39+
inputs=[],
40+
outputs=[config_status]
41+
)
42+
43+
load_config_button.click(
44+
fn=webui_manager.load_config,
45+
inputs=[config_file],
46+
outputs=[config_status]
47+
)
48+
49+
return tab_components

src/webui/interface.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from src.webui.components.agent_settings_tab import create_agent_settings_tab
55
from src.webui.components.browser_settings_tab import create_browser_settings_tab
66
from src.webui.components.browser_use_agent_tab import create_browser_use_agent_tab
7+
from src.webui.components.deep_research_agent_tab import create_deep_research_agent_tab
8+
from src.webui.components.load_save_config_tab import create_load_save_config_tab
79

810
theme_map = {
911
"Default": gr.themes.Default(),
@@ -37,10 +39,22 @@ def create_ui(theme_name="Ocean"):
3739
}
3840
"""
3941

42+
# dark mode in default
43+
js_func = """
44+
function refresh() {
45+
const url = new URL(window.location);
46+
47+
if (url.searchParams.get('__theme') !== 'dark') {
48+
url.searchParams.set('__theme', 'dark');
49+
window.location.href = url.href;
50+
}
51+
}
52+
"""
53+
4054
ui_manager = WebuiManager()
4155

4256
with gr.Blocks(
43-
title="Browser Use WebUI", theme=theme_map[theme_name], css=css
57+
title="Browser Use WebUI", theme=theme_map[theme_name], css=css, js=js_func,
4458
) as demo:
4559
with gr.Row():
4660
gr.Markdown(
@@ -62,9 +76,9 @@ def create_ui(theme_name="Ocean"):
6276
ui_manager.add_components("browser_use_agent", create_browser_use_agent_tab(ui_manager))
6377

6478
with gr.TabItem("🧐 Deep Research"):
65-
pass
79+
ui_manager.add_components("deep_research_agent", create_deep_research_agent_tab(ui_manager))
6680

67-
with gr.TabItem("📁 UI Configuration"):
68-
pass
81+
with gr.TabItem("📁 Load & Save Config"):
82+
ui_manager.add_components("load_save_config", create_load_save_config_tab(ui_manager))
6983

7084
return demo

src/webui/webui_manager.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1+
import json
12
from collections.abc import Generator
23
from typing import TYPE_CHECKING
4+
import os
5+
import gradio as gr
6+
from datetime import datetime
37

4-
if TYPE_CHECKING:
5-
from gradio.components import Component
6-
8+
from gradio.components import Component
79
from browser_use.browser.browser import Browser
810
from browser_use.browser.context import BrowserContext
911
from browser_use.agent.service import Agent
1012

1113

1214
class WebuiManager:
13-
def __init__(self):
15+
def __init__(self, settings_save_dir: str = "./tmp/webui_settings"):
1416
self.id_to_component: dict[str, Component] = {}
1517
self.component_to_id: dict[Component, str] = {}
1618

19+
self.settings_save_dir = settings_save_dir
20+
os.makedirs(self.settings_save_dir, exist_ok=True)
21+
1722
self.browser: Browser = None
1823
self.browser_context: BrowserContext = None
1924
self.bu_agent: Agent = None
@@ -44,3 +49,33 @@ def get_id_by_component(self, comp: "Component") -> str:
4449
Get id by component
4550
"""
4651
return self.component_to_id[comp]
52+
53+
def save_current_config(self):
54+
"""
55+
Save current config
56+
"""
57+
cur_settings = {}
58+
for comp_id, comp in self.id_to_component.items():
59+
if not isinstance(comp, gr.Button) and not isinstance(comp, gr.File) and str(
60+
getattr(comp, "interactive", True)).lower() != "false":
61+
cur_settings[comp_id] = getattr(comp, "value", None)
62+
63+
config_name = datetime.now().strftime("%Y%m%d-%H%M%S")
64+
with open(os.path.join(self.settings_save_dir, f"{config_name}.json"), "w") as fw:
65+
json.dump(cur_settings, fw, indent=4)
66+
67+
return os.path.join(self.settings_save_dir, f"{config_name}.json")
68+
69+
def load_config(self, config_path: str):
70+
"""
71+
Load config
72+
"""
73+
with open(config_path, "r") as fr:
74+
ui_settings = json.load(fr)
75+
76+
update_components = {}
77+
for comp_id, comp_val in ui_settings.items():
78+
if comp_id in self.id_to_component:
79+
update_components[self.id_to_component[comp_id]].value = comp_val
80+
81+
return f"Successfully loaded config from {config_path}"

0 commit comments

Comments
 (0)