HongzeFu commited on
Commit
5459e22
·
1 Parent(s): c7e75b1

ban button after execute

Browse files
gradio-web/gradio_callbacks.py CHANGED
@@ -423,23 +423,40 @@ def on_video_end_transition(uid, ui_phase=None):
423
  return on_demo_video_end_transition(uid, ui_phase)
424
 
425
 
426
- def on_execute_video_end_transition(uid, exec_btn_interactive=True):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
427
  """Transition from execute video phase back to the action phase."""
 
428
  LOGGER.debug(
429
- "on_execute_video_end_transition uid=%s exec_btn_interactive=%s",
430
  _uid_for_log(uid),
431
- exec_btn_interactive,
432
  )
433
  return (
434
  gr.update(visible=False), # execution_video_group
435
  gr.update(visible=True), # action_phase_group
436
  gr.update(visible=True), # control_panel_group
437
  gr.update(interactive=True), # options_radio
438
- gr.update(interactive=bool(exec_btn_interactive)), # exec_btn
439
  gr.update(interactive=True), # restart_episode_btn
440
  gr.update(interactive=True), # next_task_btn
441
  _live_obs_update(interactive=False), # img_display
442
- gr.update(interactive=True), # reference_action_btn
443
  gr.update(interactive=True), # task_hint_display
444
  "action_point", # ui_phase_state
445
  )
@@ -1045,7 +1062,7 @@ def execute_step(uid, option_idx, coords_str):
1045
  coords_update=None,
1046
  reference_update=gr.update(interactive=True),
1047
  task_hint_update=gr.update(interactive=True),
1048
- post_execute_exec_interactive=True,
1049
  show_execution_video=False,
1050
  ui_phase="action_point",
1051
  ):
@@ -1053,6 +1070,14 @@ def execute_step(uid, option_idx, coords_str):
1053
  execute_video_update = gr.update(value=None, visible=False, playback_position=0)
1054
  if coords_update is None:
1055
  coords_update = _ui_text("coords", "not_needed")
 
 
 
 
 
 
 
 
1056
  return (
1057
  img_update,
1058
  log_update,
@@ -1069,7 +1094,7 @@ def execute_step(uid, option_idx, coords_str):
1069
  coords_update,
1070
  reference_update,
1071
  task_hint_update,
1072
- bool(post_execute_exec_interactive),
1073
  ui_phase,
1074
  )
1075
 
@@ -1085,7 +1110,10 @@ def execute_step(uid, option_idx, coords_str):
1085
  options_update=gr.update(interactive=False),
1086
  reference_update=gr.update(interactive=False),
1087
  task_hint_update=gr.update(interactive=False),
1088
- post_execute_exec_interactive=False,
 
 
 
1089
  show_execution_video=False,
1090
  )
1091
 
@@ -1128,7 +1156,10 @@ def execute_step(uid, option_idx, coords_str):
1128
  options_update=gr.update(choices=_build_radio_choices(session), value=None, interactive=True),
1129
  reference_update=gr.update(interactive=True),
1130
  task_hint_update=gr.update(interactive=True),
1131
- post_execute_exec_interactive=True,
 
 
 
1132
  show_execution_video=False,
1133
  )
1134
 
@@ -1153,7 +1184,10 @@ def execute_step(uid, option_idx, coords_str):
1153
  coords_update=coords_str,
1154
  reference_update=gr.update(interactive=True),
1155
  task_hint_update=gr.update(interactive=True),
1156
- post_execute_exec_interactive=True,
 
 
 
1157
  show_execution_video=False,
1158
  )
1159
 
@@ -1288,13 +1322,16 @@ def execute_step(uid, option_idx, coords_str):
1288
  execute_video_update = _build_execution_video_update(uid, session)
1289
  show_execution_video = execute_video_update.get("visible") is True
1290
  radio_choices = _build_radio_choices(session)
1291
- post_execute_exec_interactive = not done
 
 
 
1292
  restart_episode_update = gr.update(interactive=False) if show_execution_video else gr.update(interactive=True)
1293
  next_task_update = gr.update(interactive=False) if show_execution_video else gr.update(interactive=True)
1294
  exec_btn_update = (
1295
  gr.update(interactive=False)
1296
  if show_execution_video
1297
- else gr.update(interactive=post_execute_exec_interactive)
1298
  )
1299
  options_update = gr.update(
1300
  choices=radio_choices,
@@ -1308,12 +1345,12 @@ def execute_step(uid, option_idx, coords_str):
1308
  # 格式化日志消息为 HTML 格式(支持颜色显示)
1309
  formatted_status = format_log_markdown(status)
1310
  LOGGER.debug(
1311
- "execute_step done uid=%s env=%s ep=%s done=%s exec_btn_interactive=%s show_execution_video=%s",
1312
  _uid_for_log(uid),
1313
  getattr(session, "env_id", None),
1314
  getattr(session, "episode_idx", None),
1315
  done,
1316
- not done,
1317
  show_execution_video,
1318
  )
1319
 
@@ -1330,7 +1367,7 @@ def execute_step(uid, option_idx, coords_str):
1330
  coords_update=coords_update,
1331
  reference_update=reference_update,
1332
  task_hint_update=task_hint_update,
1333
- post_execute_exec_interactive=post_execute_exec_interactive,
1334
  show_execution_video=show_execution_video,
1335
  ui_phase="execution_video" if show_execution_video else "action_point",
1336
  )
 
423
  return on_demo_video_end_transition(uid, ui_phase)
424
 
425
 
426
+ def _normalize_post_execute_controls_state(state):
427
+ """Normalize legacy bool and dict payloads for execute-video exit transitions."""
428
+ if isinstance(state, dict):
429
+ exec_interactive = bool(state.get("exec_btn_interactive", True))
430
+ reference_interactive = bool(state.get("reference_action_interactive", True))
431
+ return {
432
+ "exec_btn_interactive": exec_interactive,
433
+ "reference_action_interactive": reference_interactive,
434
+ }
435
+ legacy_exec_interactive = bool(state)
436
+ return {
437
+ "exec_btn_interactive": legacy_exec_interactive,
438
+ "reference_action_interactive": legacy_exec_interactive,
439
+ }
440
+
441
+
442
+ def on_execute_video_end_transition(uid, post_execute_controls_state=True):
443
  """Transition from execute video phase back to the action phase."""
444
+ controls_state = _normalize_post_execute_controls_state(post_execute_controls_state)
445
  LOGGER.debug(
446
+ "on_execute_video_end_transition uid=%s controls_state=%s",
447
  _uid_for_log(uid),
448
+ controls_state,
449
  )
450
  return (
451
  gr.update(visible=False), # execution_video_group
452
  gr.update(visible=True), # action_phase_group
453
  gr.update(visible=True), # control_panel_group
454
  gr.update(interactive=True), # options_radio
455
+ gr.update(interactive=controls_state["exec_btn_interactive"]), # exec_btn
456
  gr.update(interactive=True), # restart_episode_btn
457
  gr.update(interactive=True), # next_task_btn
458
  _live_obs_update(interactive=False), # img_display
459
+ gr.update(interactive=controls_state["reference_action_interactive"]), # reference_action_btn
460
  gr.update(interactive=True), # task_hint_display
461
  "action_point", # ui_phase_state
462
  )
 
1062
  coords_update=None,
1063
  reference_update=gr.update(interactive=True),
1064
  task_hint_update=gr.update(interactive=True),
1065
+ post_execute_controls_state=None,
1066
  show_execution_video=False,
1067
  ui_phase="action_point",
1068
  ):
 
1070
  execute_video_update = gr.update(value=None, visible=False, playback_position=0)
1071
  if coords_update is None:
1072
  coords_update = _ui_text("coords", "not_needed")
1073
+ if post_execute_controls_state is None:
1074
+ post_execute_controls_state = {
1075
+ "exec_btn_interactive": True,
1076
+ "reference_action_interactive": True,
1077
+ }
1078
+ normalized_post_execute_controls_state = _normalize_post_execute_controls_state(
1079
+ post_execute_controls_state
1080
+ )
1081
  return (
1082
  img_update,
1083
  log_update,
 
1094
  coords_update,
1095
  reference_update,
1096
  task_hint_update,
1097
+ normalized_post_execute_controls_state,
1098
  ui_phase,
1099
  )
1100
 
 
1110
  options_update=gr.update(interactive=False),
1111
  reference_update=gr.update(interactive=False),
1112
  task_hint_update=gr.update(interactive=False),
1113
+ post_execute_controls_state={
1114
+ "exec_btn_interactive": False,
1115
+ "reference_action_interactive": False,
1116
+ },
1117
  show_execution_video=False,
1118
  )
1119
 
 
1156
  options_update=gr.update(choices=_build_radio_choices(session), value=None, interactive=True),
1157
  reference_update=gr.update(interactive=True),
1158
  task_hint_update=gr.update(interactive=True),
1159
+ post_execute_controls_state={
1160
+ "exec_btn_interactive": True,
1161
+ "reference_action_interactive": True,
1162
+ },
1163
  show_execution_video=False,
1164
  )
1165
 
 
1184
  coords_update=coords_str,
1185
  reference_update=gr.update(interactive=True),
1186
  task_hint_update=gr.update(interactive=True),
1187
+ post_execute_controls_state={
1188
+ "exec_btn_interactive": True,
1189
+ "reference_action_interactive": True,
1190
+ },
1191
  show_execution_video=False,
1192
  )
1193
 
 
1322
  execute_video_update = _build_execution_video_update(uid, session)
1323
  show_execution_video = execute_video_update.get("visible") is True
1324
  radio_choices = _build_radio_choices(session)
1325
+ post_execute_controls_state = {
1326
+ "exec_btn_interactive": not done,
1327
+ "reference_action_interactive": not done,
1328
+ }
1329
  restart_episode_update = gr.update(interactive=False) if show_execution_video else gr.update(interactive=True)
1330
  next_task_update = gr.update(interactive=False) if show_execution_video else gr.update(interactive=True)
1331
  exec_btn_update = (
1332
  gr.update(interactive=False)
1333
  if show_execution_video
1334
+ else gr.update(interactive=post_execute_controls_state["exec_btn_interactive"])
1335
  )
1336
  options_update = gr.update(
1337
  choices=radio_choices,
 
1345
  # 格式化日志消息为 HTML 格式(支持颜色显示)
1346
  formatted_status = format_log_markdown(status)
1347
  LOGGER.debug(
1348
+ "execute_step done uid=%s env=%s ep=%s done=%s post_execute_controls=%s show_execution_video=%s",
1349
  _uid_for_log(uid),
1350
  getattr(session, "env_id", None),
1351
  getattr(session, "episode_idx", None),
1352
  done,
1353
+ post_execute_controls_state,
1354
  show_execution_video,
1355
  )
1356
 
 
1367
  coords_update=coords_update,
1368
  reference_update=reference_update,
1369
  task_hint_update=task_hint_update,
1370
+ post_execute_controls_state=post_execute_controls_state,
1371
  show_execution_video=show_execution_video,
1372
  ui_phase="execution_video" if show_execution_video else "action_point",
1373
  )
gradio-web/test/test_ui_phase_machine_runtime_e2e.py CHANGED
@@ -2556,7 +2556,7 @@ def test_header_task_switch_to_video_task_shows_demo_phase(monkeypatch):
2556
  demo.close()
2557
 
2558
 
2559
- def test_phase_machine_runtime_local_video_path_end_transition():
2560
  import gradio_callbacks as cb
2561
  import config as config_module
2562
 
@@ -2590,7 +2590,7 @@ def test_phase_machine_runtime_local_video_path_end_transition():
2590
  _ = option_idx, click_coords
2591
  self.last_execution_frames = [fake_obs.copy() for _ in range(3)]
2592
  self.base_frames.extend(self.last_execution_frames)
2593
- return fake_obs.copy(), "Executing: pick", False
2594
 
2595
  originals = {
2596
  "get_session": cb.get_session,
@@ -2608,7 +2608,12 @@ def test_phase_machine_runtime_local_video_path_end_transition():
2608
  with gr.Blocks(title="Native phase machine local video test") as demo:
2609
  uid_state = gr.State(value="uid-local-video")
2610
  phase_state = gr.State(value="action_point")
2611
- post_execute_exec_state = gr.State(value=True)
 
 
 
 
 
2612
  suppress_state = gr.State(value=False)
2613
  with gr.Column(visible=True, elem_id="main_interface") as main_interface:
2614
  with gr.Column(visible=False, elem_id="video_phase_group") as video_phase_group:
@@ -2676,7 +2681,7 @@ def test_phase_machine_runtime_local_video_path_end_transition():
2676
  coords_box,
2677
  reference_action_btn,
2678
  task_hint_display,
2679
- post_execute_exec_state,
2680
  phase_state,
2681
  ],
2682
  queue=False,
@@ -2690,7 +2695,7 @@ def test_phase_machine_runtime_local_video_path_end_transition():
2690
 
2691
  execute_video_display.end(
2692
  fn=cb.on_execute_video_end_transition,
2693
- inputs=[uid_state, post_execute_exec_state],
2694
  outputs=[
2695
  execution_video_group,
2696
  action_phase_group,
@@ -2708,7 +2713,7 @@ def test_phase_machine_runtime_local_video_path_end_transition():
2708
  )
2709
  execute_video_display.stop(
2710
  fn=cb.on_execute_video_end_transition,
2711
- inputs=[uid_state, post_execute_exec_state],
2712
  outputs=[
2713
  execution_video_group,
2714
  action_phase_group,
@@ -2818,30 +2823,66 @@ def test_phase_machine_runtime_local_video_path_end_transition():
2818
  }""",
2819
  timeout=2000,
2820
  )
2821
- page.locator("#action_radio input[type='radio']").nth(1).check(force=True)
2822
- page.wait_for_function(
2823
- """(state) => {
2824
- const liveObs = document.getElementById('live_obs');
2825
- const coordsRoot = document.getElementById('coords_box');
2826
- const coordsField = coordsRoot?.querySelector('textarea, input');
2827
- const logRoot = document.getElementById('log_output');
2828
- const logField = logRoot?.querySelector('textarea, input');
2829
- const coordsValue = coordsField ? coordsField.value.trim() : '';
2830
- const logValue = logField ? logField.value.trim() : (logRoot?.textContent || '').trim();
2831
- return (
2832
- !!liveObs &&
2833
- liveObs.classList.contains(state.waitClass) &&
2834
- coordsValue === state.coordsPrompt &&
2835
- logValue === state.waitLog
2836
- );
2837
- }""",
2838
- arg={
2839
- "waitClass": config_module.LIVE_OBS_POINT_WAIT_CLASS,
2840
- "coordsPrompt": config_module.UI_TEXT["coords"]["select_point"],
2841
- "waitLog": config_module.UI_TEXT["log"]["point_selection_prompt"],
2842
- },
2843
- timeout=5000,
2844
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2845
 
2846
  browser.close()
2847
  finally:
@@ -2851,3 +2892,27 @@ def test_phase_machine_runtime_local_video_path_end_transition():
2851
  finally:
2852
  for name, value in originals.items():
2853
  setattr(cb, name, value)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2556
  demo.close()
2557
 
2558
 
2559
+ def _run_local_execute_video_transition_test(*, status_text, done, expect_terminal_buttons_disabled):
2560
  import gradio_callbacks as cb
2561
  import config as config_module
2562
 
 
2590
  _ = option_idx, click_coords
2591
  self.last_execution_frames = [fake_obs.copy() for _ in range(3)]
2592
  self.base_frames.extend(self.last_execution_frames)
2593
+ return fake_obs.copy(), status_text, done
2594
 
2595
  originals = {
2596
  "get_session": cb.get_session,
 
2608
  with gr.Blocks(title="Native phase machine local video test") as demo:
2609
  uid_state = gr.State(value="uid-local-video")
2610
  phase_state = gr.State(value="action_point")
2611
+ post_execute_controls_state = gr.State(
2612
+ value={
2613
+ "exec_btn_interactive": True,
2614
+ "reference_action_interactive": True,
2615
+ }
2616
+ )
2617
  suppress_state = gr.State(value=False)
2618
  with gr.Column(visible=True, elem_id="main_interface") as main_interface:
2619
  with gr.Column(visible=False, elem_id="video_phase_group") as video_phase_group:
 
2681
  coords_box,
2682
  reference_action_btn,
2683
  task_hint_display,
2684
+ post_execute_controls_state,
2685
  phase_state,
2686
  ],
2687
  queue=False,
 
2695
 
2696
  execute_video_display.end(
2697
  fn=cb.on_execute_video_end_transition,
2698
+ inputs=[uid_state, post_execute_controls_state],
2699
  outputs=[
2700
  execution_video_group,
2701
  action_phase_group,
 
2713
  )
2714
  execute_video_display.stop(
2715
  fn=cb.on_execute_video_end_transition,
2716
+ inputs=[uid_state, post_execute_controls_state],
2717
  outputs=[
2718
  execution_video_group,
2719
  action_phase_group,
 
2823
  }""",
2824
  timeout=2000,
2825
  )
2826
+ if expect_terminal_buttons_disabled:
2827
+ button_snapshot = page.evaluate(
2828
+ """() => {
2829
+ const resolveButton = (id) => {
2830
+ return document.querySelector(`#${id} button`) || document.querySelector(`button#${id}`);
2831
+ };
2832
+ const execBtn = resolveButton('exec_btn');
2833
+ const refBtn = resolveButton('reference_action_btn');
2834
+ return {
2835
+ execDisabled: execBtn ? execBtn.disabled : null,
2836
+ refDisabled: refBtn ? refBtn.disabled : null,
2837
+ };
2838
+ }"""
2839
+ )
2840
+ assert button_snapshot == {
2841
+ "execDisabled": True,
2842
+ "refDisabled": True,
2843
+ }
2844
+ else:
2845
+ button_snapshot = page.evaluate(
2846
+ """() => {
2847
+ const resolveButton = (id) => {
2848
+ return document.querySelector(`#${id} button`) || document.querySelector(`button#${id}`);
2849
+ };
2850
+ const execBtn = resolveButton('exec_btn');
2851
+ const refBtn = resolveButton('reference_action_btn');
2852
+ return {
2853
+ execDisabled: execBtn ? execBtn.disabled : null,
2854
+ refDisabled: refBtn ? refBtn.disabled : null,
2855
+ };
2856
+ }"""
2857
+ )
2858
+ assert button_snapshot == {
2859
+ "execDisabled": False,
2860
+ "refDisabled": False,
2861
+ }
2862
+ page.locator("#action_radio input[type='radio']").nth(1).check(force=True)
2863
+ page.wait_for_function(
2864
+ """(state) => {
2865
+ const liveObs = document.getElementById('live_obs');
2866
+ const coordsRoot = document.getElementById('coords_box');
2867
+ const coordsField = coordsRoot?.querySelector('textarea, input');
2868
+ const logRoot = document.getElementById('log_output');
2869
+ const logField = logRoot?.querySelector('textarea, input');
2870
+ const coordsValue = coordsField ? coordsField.value.trim() : '';
2871
+ const logValue = logField ? logField.value.trim() : (logRoot?.textContent || '').trim();
2872
+ return (
2873
+ !!liveObs &&
2874
+ liveObs.classList.contains(state.waitClass) &&
2875
+ coordsValue === state.coordsPrompt &&
2876
+ logValue === state.waitLog
2877
+ );
2878
+ }""",
2879
+ arg={
2880
+ "waitClass": config_module.LIVE_OBS_POINT_WAIT_CLASS,
2881
+ "coordsPrompt": config_module.UI_TEXT["coords"]["select_point"],
2882
+ "waitLog": config_module.UI_TEXT["log"]["point_selection_prompt"],
2883
+ },
2884
+ timeout=5000,
2885
+ )
2886
 
2887
  browser.close()
2888
  finally:
 
2892
  finally:
2893
  for name, value in originals.items():
2894
  setattr(cb, name, value)
2895
+
2896
+
2897
+ def test_phase_machine_runtime_local_video_path_end_transition():
2898
+ _run_local_execute_video_transition_test(
2899
+ status_text="Executing: pick",
2900
+ done=False,
2901
+ expect_terminal_buttons_disabled=False,
2902
+ )
2903
+
2904
+
2905
+ def test_phase_machine_runtime_local_video_path_end_transition_terminal_success():
2906
+ _run_local_execute_video_transition_test(
2907
+ status_text="SUCCESS",
2908
+ done=True,
2909
+ expect_terminal_buttons_disabled=True,
2910
+ )
2911
+
2912
+
2913
+ def test_phase_machine_runtime_local_video_path_end_transition_terminal_failed():
2914
+ _run_local_execute_video_transition_test(
2915
+ status_text="Executing: pick | FAILED",
2916
+ done=True,
2917
+ expect_terminal_buttons_disabled=True,
2918
+ )
gradio-web/test/test_ui_text_config.py CHANGED
@@ -83,16 +83,22 @@ def test_on_video_end_transition_uses_configured_action_prompt(monkeypatch, relo
83
  assert result[5] == "action_point"
84
 
85
 
86
- def test_on_execute_video_end_transition_preserves_log_and_restores_controls(reload_module):
87
  callbacks = reload_module("gradio_callbacks")
88
 
89
- result = callbacks.on_execute_video_end_transition("uid-1", False)
 
 
 
 
 
 
90
 
91
  assert result[0]["visible"] is False
92
  assert result[1]["visible"] is True
93
  assert result[2]["visible"] is True
94
  assert result[3]["interactive"] is True
95
- assert result[4]["interactive"] is False
96
  assert result[5]["interactive"] is True
97
  assert result[6]["interactive"] is True
98
  assert result[8]["interactive"] is True
@@ -100,6 +106,29 @@ def test_on_execute_video_end_transition_preserves_log_and_restores_controls(rel
100
  assert result[10] == "action_point"
101
 
102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  def test_on_demo_video_play_disables_button_and_sets_single_use_state(monkeypatch, reload_module):
104
  reload_module("config")
105
  callbacks = reload_module("gradio_callbacks")
 
83
  assert result[5] == "action_point"
84
 
85
 
86
+ def test_on_execute_video_end_transition_restores_controls_for_non_terminal_state(reload_module):
87
  callbacks = reload_module("gradio_callbacks")
88
 
89
+ result = callbacks.on_execute_video_end_transition(
90
+ "uid-1",
91
+ {
92
+ "exec_btn_interactive": True,
93
+ "reference_action_interactive": True,
94
+ },
95
+ )
96
 
97
  assert result[0]["visible"] is False
98
  assert result[1]["visible"] is True
99
  assert result[2]["visible"] is True
100
  assert result[3]["interactive"] is True
101
+ assert result[4]["interactive"] is True
102
  assert result[5]["interactive"] is True
103
  assert result[6]["interactive"] is True
104
  assert result[8]["interactive"] is True
 
106
  assert result[10] == "action_point"
107
 
108
 
109
+ def test_on_execute_video_end_transition_keeps_terminal_buttons_disabled(reload_module):
110
+ callbacks = reload_module("gradio_callbacks")
111
+
112
+ result = callbacks.on_execute_video_end_transition(
113
+ "uid-1",
114
+ {
115
+ "exec_btn_interactive": False,
116
+ "reference_action_interactive": False,
117
+ },
118
+ )
119
+
120
+ assert result[0]["visible"] is False
121
+ assert result[1]["visible"] is True
122
+ assert result[2]["visible"] is True
123
+ assert result[3]["interactive"] is True
124
+ assert result[4]["interactive"] is False
125
+ assert result[5]["interactive"] is True
126
+ assert result[6]["interactive"] is True
127
+ assert result[8]["interactive"] is False
128
+ assert result[9]["interactive"] is True
129
+ assert result[10] == "action_point"
130
+
131
+
132
  def test_on_demo_video_play_disables_button_and_sets_single_use_state(monkeypatch, reload_module):
133
  reload_module("config")
134
  callbacks = reload_module("gradio_callbacks")
gradio-web/ui_layout.py CHANGED
@@ -952,7 +952,12 @@ def create_ui_blocks():
952
  delete_callback=cleanup_user_session,
953
  )
954
  ui_phase_state = gr.State(value=PHASE_INIT)
955
- post_execute_exec_interactive_state = gr.State(value=True)
 
 
 
 
 
956
  current_task_env_state = gr.State(value=None)
957
  suppress_next_option_change_state = gr.State(value=False)
958
 
@@ -1393,7 +1398,7 @@ def create_ui_blocks():
1393
 
1394
  execute_video_display.end(
1395
  fn=on_execute_video_end_transition,
1396
- inputs=[uid_state, post_execute_exec_interactive_state],
1397
  outputs=[
1398
  execution_video_group,
1399
  action_phase_group,
@@ -1418,7 +1423,7 @@ def create_ui_blocks():
1418
  )
1419
  execute_video_display.stop(
1420
  fn=on_execute_video_end_transition,
1421
- inputs=[uid_state, post_execute_exec_interactive_state],
1422
  outputs=[
1423
  execution_video_group,
1424
  action_phase_group,
@@ -1542,7 +1547,7 @@ def create_ui_blocks():
1542
  coords_box,
1543
  reference_action_btn,
1544
  task_hint_display,
1545
- post_execute_exec_interactive_state,
1546
  ui_phase_state,
1547
  ],
1548
  show_progress="hidden",
 
952
  delete_callback=cleanup_user_session,
953
  )
954
  ui_phase_state = gr.State(value=PHASE_INIT)
955
+ post_execute_controls_state = gr.State(
956
+ value={
957
+ "exec_btn_interactive": True,
958
+ "reference_action_interactive": True,
959
+ }
960
+ )
961
  current_task_env_state = gr.State(value=None)
962
  suppress_next_option_change_state = gr.State(value=False)
963
 
 
1398
 
1399
  execute_video_display.end(
1400
  fn=on_execute_video_end_transition,
1401
+ inputs=[uid_state, post_execute_controls_state],
1402
  outputs=[
1403
  execution_video_group,
1404
  action_phase_group,
 
1423
  )
1424
  execute_video_display.stop(
1425
  fn=on_execute_video_end_transition,
1426
+ inputs=[uid_state, post_execute_controls_state],
1427
  outputs=[
1428
  execution_video_group,
1429
  action_phase_group,
 
1547
  coords_box,
1548
  reference_action_btn,
1549
  task_hint_display,
1550
+ post_execute_controls_state,
1551
  ui_phase_state,
1552
  ],
1553
  show_progress="hidden",