Skip to content

Commit 8645d55

Browse files
authored
Merge pull request #548 from PlanExeOrg/fix/settings-tab-hang
Fix Gradio UI freezing when switching tabs
2 parents b449fd6 + b487278 commit 8645d55

1 file changed

Lines changed: 48 additions & 51 deletions

File tree

frontend_single_user/app.py

Lines changed: 48 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,11 @@ def initialize_browser_settings(browser_state, session_state: SessionState):
382382
session_state.speedvsdetail = speedvsdetail
383383
session_state.model_profile = model_profile
384384
profile_markdown = _profile_models_markdown(model_profile)
385-
return openrouter_api_key, model, speedvsdetail, model_profile, profile_markdown, "", browser_state, session_state
385+
open_dir_visible = gr.update(visible=is_open_dir_service_running())
386+
return openrouter_api_key, model, speedvsdetail, model_profile, profile_markdown, "", open_dir_visible, browser_state, session_state
386387

387-
def update_browser_settings_callback(openrouter_api_key, model, speedvsdetail, model_profile, browser_state, session_state: SessionState):
388+
def save_browser_settings_callback(openrouter_api_key, model, speedvsdetail, model_profile, browser_state):
389+
"""Persist current settings to BrowserState. Called on submit/retry, not on every change."""
388390
try:
389391
settings = json.loads(browser_state) if browser_state else {}
390392
except Exception:
@@ -393,13 +395,7 @@ def update_browser_settings_callback(openrouter_api_key, model, speedvsdetail, m
393395
settings["model_radio"] = model
394396
settings["speedvsdetail_radio"] = speedvsdetail
395397
settings["model_profile_radio"] = model_profile
396-
updated_browser_state = json.dumps(settings)
397-
session_state.openrouter_api_key = openrouter_api_key
398-
session_state.llm_model = model
399-
session_state.speedvsdetail = speedvsdetail
400-
session_state.model_profile = model_profile
401-
profile_markdown = _profile_models_markdown(model_profile)
402-
return updated_browser_state, openrouter_api_key, model, speedvsdetail, model_profile, profile_markdown, "", session_state
398+
return json.dumps(settings)
403399

404400
def run_planner(submit_or_retry_button, plan_prompt, browser_state, session_state: SessionState):
405401
"""
@@ -765,7 +761,7 @@ def check_api_key(session_state: SessionState):
765761
speedvsdetail_items,
766762
value=SpeedVsDetailEnum.ALL_DETAILS_BUT_SLOW,
767763
label="Speed vs Detail",
768-
interactive=True
764+
interactive=True
769765
)
770766

771767
if CONFIG.visible_llm_info:
@@ -783,7 +779,7 @@ def check_api_key(session_state: SessionState):
783779
available_model_names,
784780
value=default_model_value,
785781
label="Model",
786-
interactive=True
782+
interactive=True
787783
)
788784

789785
model_profile_radio = gr.Radio(
@@ -848,6 +844,10 @@ def check_api_key(session_state: SessionState):
848844
fn=clear_status,
849845
inputs=session_state,
850846
outputs=[status_markdown, session_state]
847+
).then(
848+
fn=save_browser_settings_callback,
849+
inputs=[openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, browser_state],
850+
outputs=[browser_state]
851851
).then(
852852
fn=run_planner,
853853
inputs=[submit_btn, prompt_input, browser_state, session_state],
@@ -861,6 +861,10 @@ def check_api_key(session_state: SessionState):
861861
fn=clear_status,
862862
inputs=session_state,
863863
outputs=[status_markdown, session_state]
864+
).then(
865+
fn=save_browser_settings_callback,
866+
inputs=[openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, browser_state],
867+
outputs=[browser_state]
864868
).then(
865869
fn=run_planner,
866870
inputs=[retry_btn, prompt_input, browser_state, session_state],
@@ -888,67 +892,60 @@ def check_api_key(session_state: SessionState):
888892
)
889893
# The download file value is updated by run_planner generator outputs.
890894

891-
# Unified change callbacks for settings.
895+
# Settings change callbacks — update session_state and profile display.
896+
settings_change_inputs = [openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, session_state]
897+
settings_change_outputs = [profile_models_markdown, active_config_markdown, session_state]
898+
899+
def update_settings_on_change(openrouter_api_key, model, speedvsdetail, model_profile, session_state: SessionState):
900+
session_state.openrouter_api_key = openrouter_api_key
901+
session_state.llm_model = model
902+
session_state.speedvsdetail = speedvsdetail
903+
session_state.model_profile = model_profile
904+
profile_markdown = _profile_models_markdown(model_profile)
905+
return profile_markdown, "", session_state
906+
892907
openrouter_api_key_text.change(
893-
fn=update_browser_settings_callback,
894-
inputs=[openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, browser_state, session_state],
895-
outputs=[browser_state, openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, profile_models_markdown, active_config_markdown, session_state]
896-
).then(
897-
fn=check_api_key,
898-
inputs=[session_state],
899-
outputs=[api_key_warning]
900-
)
908+
fn=update_settings_on_change,
909+
inputs=settings_change_inputs,
910+
outputs=settings_change_outputs,
911+
).then(fn=check_api_key, inputs=[session_state], outputs=[api_key_warning])
901912

902913
model_radio.change(
903-
fn=update_browser_settings_callback,
904-
inputs=[openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, browser_state, session_state],
905-
outputs=[browser_state, openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, profile_models_markdown, active_config_markdown, session_state]
906-
).then(
907-
fn=check_api_key,
908-
inputs=[session_state],
909-
outputs=[api_key_warning]
910-
)
914+
fn=update_settings_on_change,
915+
inputs=settings_change_inputs,
916+
outputs=settings_change_outputs,
917+
).then(fn=check_api_key, inputs=[session_state], outputs=[api_key_warning])
911918

912919
speedvsdetail_radio.change(
913-
fn=update_browser_settings_callback,
914-
inputs=[openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, browser_state, session_state],
915-
outputs=[browser_state, openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, profile_models_markdown, active_config_markdown, session_state]
916-
).then(
917-
fn=check_api_key,
918-
inputs=[session_state],
919-
outputs=[api_key_warning]
920-
)
920+
fn=update_settings_on_change,
921+
inputs=settings_change_inputs,
922+
outputs=settings_change_outputs,
923+
).then(fn=check_api_key, inputs=[session_state], outputs=[api_key_warning])
921924

922925
model_profile_radio.change(
923-
fn=update_browser_settings_callback,
924-
inputs=[openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, browser_state, session_state],
925-
outputs=[browser_state, openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, profile_models_markdown, active_config_markdown, session_state]
926-
).then(
927-
fn=check_api_key,
928-
inputs=[session_state],
929-
outputs=[api_key_warning]
930-
)
926+
fn=update_settings_on_change,
927+
inputs=settings_change_inputs,
928+
outputs=settings_change_outputs,
929+
).then(fn=check_api_key, inputs=[session_state], outputs=[api_key_warning])
931930

932931
purge_button.click(
933932
fn=trigger_purge_runs,
934933
inputs=[purge_max_age_hours, session_state],
935934
outputs=[purge_status, session_state]
936935
)
937936

938-
# Initialize settings on load from persistent browser_state.
939-
demo_text2plan.load(
937+
# Restore settings from BrowserState when it loads from localStorage.
938+
# We use browser_state.change instead of demo_text2plan.load because
939+
# Gradio 6.11 has a bug where .load with outputs breaks tab switching.
940+
browser_state.change(
940941
fn=initialize_browser_settings,
941942
inputs=[browser_state, session_state],
942-
outputs=[openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, profile_models_markdown, active_config_markdown, browser_state, session_state]
943+
outputs=[openrouter_api_key_text, model_radio, speedvsdetail_radio, model_profile_radio, profile_models_markdown, active_config_markdown, open_dir_btn, browser_state, session_state]
943944
).then(
944945
fn=check_api_key,
945946
inputs=[session_state],
946947
outputs=[api_key_warning]
947948
)
948-
demo_text2plan.load(
949-
fn=update_open_dir_button_visibility,
950-
outputs=[open_dir_btn]
951-
)
952949

953950
def run_app():
954951
# print("Environment variables Gradio:\n" + get_env_as_string() + "\n\n\n")

0 commit comments

Comments
 (0)