HongzeFu commited on
Commit
02e3d3d
·
1 Parent(s): 49f2d91

Capitalize

Browse files
gradio-web/config.py CHANGED
@@ -40,9 +40,9 @@ DEMO_VIDEO_ENV_IDS = [
40
 
41
  UI_TEXT = {
42
  "log": {
43
- "action_selection_prompt": "please select the action in the left 👈,\nsome actions also need to select keypoint",
44
- "keypoint_selection_prompt": "current action needs location input, please click on the image to select key pixel",
45
- "demo_video_prompt": 'press "Watch Video Input🎬" to watch a video\nNote: you can only watch the video once',
46
  "session_error": "Session Error",
47
  "reference_action_error": "Ground Truth Action Error: {error}",
48
  "reference_action_message": "Ground Truth Action: {option_label}. {option_action}",
@@ -54,11 +54,11 @@ UI_TEXT = {
54
  },
55
  "coords": {
56
  "not_needed": "No need for coordinates",
57
- "select_keypoint": "please click the keypoint selection image",
58
- "select_keypoint_before_execute": "please click the keypoint selection image before execute!",
59
  },
60
  "actions": {
61
- "keypoint_required_suffix": "🎯",
62
  },
63
  "errors": {
64
  "load_missing_task": "Error loading task: missing current_task",
 
40
 
41
  UI_TEXT = {
42
  "log": {
43
+ "action_selection_prompt": "Please select the action in the left 👈,\nSome actions also need to select keypoint",
44
+ "keypoint_selection_prompt": "Current action needs location input, please click on the image to select key pixel",
45
+ "demo_video_prompt": 'Press "Watch Video Input🎬" to watch a video\nNote: you can only watch the video once',
46
  "session_error": "Session Error",
47
  "reference_action_error": "Ground Truth Action Error: {error}",
48
  "reference_action_message": "Ground Truth Action: {option_label}. {option_action}",
 
54
  },
55
  "coords": {
56
  "not_needed": "No need for coordinates",
57
+ "select_keypoint": "Please click the keypoint selection image",
58
+ "select_keypoint_before_execute": "Please click the keypoint selection image before execute!",
59
  },
60
  "actions": {
61
+ "keypoint_required_suffix": " 🎯",
62
  },
63
  "errors": {
64
  "load_missing_task": "Error loading task: missing current_task",
gradio-web/test/test_ui_native_layout_contract.py CHANGED
@@ -70,6 +70,14 @@ def test_extract_last_goal_prefers_last_list_item(reload_module):
70
  assert ui_layout.extract_last_goal("['goal a', 'goal b']") == "goal b"
71
 
72
 
 
 
 
 
 
 
 
 
73
  def test_native_ui_config_contains_phase_machine_and_precheck_chain(reload_module):
74
  ui_layout = reload_module("ui_layout")
75
  demo = ui_layout.create_ui_blocks()
 
70
  assert ui_layout.extract_last_goal("['goal a', 'goal b']") == "goal b"
71
 
72
 
73
+ def test_render_header_goal_capitalizes_display_value(reload_module):
74
+ ui_layout = reload_module("ui_layout")
75
+
76
+ assert ui_layout.render_header_goal("place cube on target") == "Place cube on target"
77
+ assert ui_layout.render_header_goal("['goal a', 'goal b']") == "Goal b"
78
+ assert ui_layout.render_header_goal("") == "—"
79
+
80
+
81
  def test_native_ui_config_contains_phase_machine_and_precheck_chain(reload_module):
82
  ui_layout = reload_module("ui_layout")
83
  demo = ui_layout.create_ui_blocks()
gradio-web/test/test_ui_phase_machine_runtime_e2e.py CHANGED
@@ -87,6 +87,19 @@ def _read_header_task_value(page) -> str | None:
87
  )
88
 
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  def _read_coords_box_value(page) -> str | None:
91
  return page.evaluate(
92
  """() => {
@@ -1552,6 +1565,77 @@ def test_header_task_shows_env_after_init(monkeypatch):
1552
  timeout=5000,
1553
  )
1554
  assert _read_header_task_value(page) == "PickXtimes"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1555
  browser.close()
1556
  finally:
1557
  server.should_exit = True
 
87
  )
88
 
89
 
90
+ def _read_header_goal_value(page) -> str | None:
91
+ return page.evaluate(
92
+ """() => {
93
+ const root = document.getElementById('header_goal');
94
+ if (!root) return null;
95
+ const field = root.querySelector('textarea, input');
96
+ if (!field) return null;
97
+ const value = typeof field.value === 'string' ? field.value.trim() : '';
98
+ return value || null;
99
+ }"""
100
+ )
101
+
102
+
103
  def _read_coords_box_value(page) -> str | None:
104
  return page.evaluate(
105
  """() => {
 
1565
  timeout=5000,
1566
  )
1567
  assert _read_header_task_value(page) == "PickXtimes"
1568
+ assert _read_header_goal_value(page) == "Goal"
1569
+ browser.close()
1570
+ finally:
1571
+ server.should_exit = True
1572
+ thread.join(timeout=10)
1573
+ demo.close()
1574
+
1575
+
1576
+ def test_header_goal_capitalizes_displayed_value_after_init(monkeypatch):
1577
+ ui_layout = importlib.reload(importlib.import_module("ui_layout"))
1578
+
1579
+ fake_obs = np.zeros((24, 24, 3), dtype=np.uint8)
1580
+ fake_obs_img = Image.fromarray(fake_obs)
1581
+
1582
+ def fake_init_app(request=None):
1583
+ _ = request
1584
+ return (
1585
+ "uid-auto",
1586
+ gr.update(visible=True), # main_interface
1587
+ gr.update(value=fake_obs_img, interactive=False), # img_display
1588
+ "ready", # log_output
1589
+ gr.update(choices=[("pick", 0)], value=None), # options_radio
1590
+ "place cube on target", # goal_box
1591
+ "No need for coordinates", # coords_box
1592
+ gr.update(value=None, visible=False), # video_display
1593
+ gr.update(visible=False, interactive=False), # watch_demo_video_btn
1594
+ "PickXtimes (Episode 1)", # task_info_box
1595
+ "Completed: 0", # progress_info_box
1596
+ gr.update(interactive=True), # restart_episode_btn
1597
+ gr.update(interactive=True), # next_task_btn
1598
+ gr.update(interactive=True), # exec_btn
1599
+ gr.update(visible=False), # video_phase_group
1600
+ gr.update(visible=True), # action_phase_group
1601
+ gr.update(visible=True), # control_panel_group
1602
+ gr.update(value="hint"), # task_hint_display
1603
+ gr.update(visible=False), # loading_overlay
1604
+ gr.update(interactive=True), # reference_action_btn
1605
+ )
1606
+
1607
+ monkeypatch.setattr(ui_layout, "init_app", fake_init_app)
1608
+
1609
+ demo = ui_layout.create_ui_blocks()
1610
+
1611
+ port = _free_port()
1612
+ host = "127.0.0.1"
1613
+ root_url = f"http://{host}:{port}/"
1614
+
1615
+ app = FastAPI(title="header-goal-capitalization-test")
1616
+ app = gr.mount_gradio_app(app, demo, path="/")
1617
+
1618
+ config = uvicorn.Config(app, host=host, port=port, log_level="error")
1619
+ server = uvicorn.Server(config)
1620
+ thread = threading.Thread(target=server.run, daemon=True)
1621
+ thread.start()
1622
+ _wait_http_ready(root_url)
1623
+
1624
+ try:
1625
+ with sync_playwright() as p:
1626
+ browser = p.chromium.launch(headless=True)
1627
+ page = browser.new_page(viewport={"width": 1280, "height": 900})
1628
+ page.goto(root_url, wait_until="domcontentloaded")
1629
+ page.wait_for_selector("#main_interface_root", state="visible", timeout=15000)
1630
+ page.wait_for_function(
1631
+ """() => {
1632
+ const root = document.getElementById('header_goal');
1633
+ const input = root ? root.querySelector('textarea, input') : null;
1634
+ return !!input && input.value.trim() === 'Place cube on target';
1635
+ }""",
1636
+ timeout=5000,
1637
+ )
1638
+ assert _read_header_goal_value(page) == "Place cube on target"
1639
  browser.close()
1640
  finally:
1641
  server.should_exit = True
gradio-web/ui_layout.py CHANGED
@@ -391,6 +391,23 @@ def extract_last_goal(goal_text):
391
  return text.split("\n")[0].strip()
392
 
393
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
394
  def _phase_from_updates(main_interface_update, video_phase_update):
395
  if isinstance(main_interface_update, dict) and main_interface_update.get("visible") is False:
396
  return PHASE_INIT
@@ -442,10 +459,6 @@ def create_ui_blocks():
442
  clean_task = clean_task.split(marker, 1)[0].strip()
443
  return " ".join(clean_task.splitlines()).strip() or None
444
 
445
- def render_header_goal(goal_text):
446
- last_goal = extract_last_goal(goal_text or "")
447
- return last_goal if last_goal else "—"
448
-
449
  with gr.Blocks(title="Oracle Planner Interface") as demo:
450
  demo.css = CSS
451
 
 
391
  return text.split("\n")[0].strip()
392
 
393
 
394
+ def capitalize_first_letter(text):
395
+ """Uppercase only the first character for display."""
396
+ if not text:
397
+ return text
398
+ if len(text) == 1:
399
+ return text.upper()
400
+ return text[0].upper() + text[1:]
401
+
402
+
403
+ def render_header_goal(goal_text):
404
+ """Render header goal from raw goal text using display-only normalization."""
405
+ last_goal = extract_last_goal(goal_text or "")
406
+ if not last_goal:
407
+ return "—"
408
+ return capitalize_first_letter(last_goal)
409
+
410
+
411
  def _phase_from_updates(main_interface_update, video_phase_update):
412
  if isinstance(main_interface_update, dict) and main_interface_update.get("visible") is False:
413
  return PHASE_INIT
 
459
  clean_task = clean_task.split(marker, 1)[0].strip()
460
  return " ".join(clean_task.splitlines()).strip() or None
461
 
 
 
 
 
462
  with gr.Blocks(title="Oracle Planner Interface") as demo:
463
  demo.css = CSS
464