From 564b2b51cc904a5a38809292aa699d2e39c67d04 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Tue, 23 Dec 2025 16:09:17 -0800 Subject: [PATCH] Fix for dev env --- litellm/proxy/proxy_server.py | 25 +++++++++++-------- tests/test_litellm/proxy/test_proxy_server.py | 25 ++++++++++--------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index a1be8153b29..f56c0c2b07a 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -992,7 +992,6 @@ try: f"Using packaged UI directory for local development: {packaged_ui_path}" ) ui_path = packaged_ui_path - # Only modify files if a custom server root path is set if server_root_path and server_root_path != "/": # Iterate through files in the UI directory @@ -1078,18 +1077,22 @@ try: continue # Handle HTML file restructuring - # Always restructure the directory we actually serve, but avoid mutating the packaged UI. + # Always restructure the directory we actually serve. # This is critical for extensionless routes like /ui/login (expects login/index.html). - if ui_path != packaged_ui_path: - try: - _restructure_ui_html_files(ui_path) - except PermissionError as e: - verbose_proxy_logger.exception( - f"Permission error while restructuring UI directory {ui_path}: {e}" - ) - else: + # In development, we restructure directly in _experimental/out. + # In non-root Docker, we restructure in /var/lib/litellm/ui. + try: + _restructure_ui_html_files(ui_path) verbose_proxy_logger.info( - f"Skipping runtime HTML restructuring for packaged UI directory: {ui_path}" + f"Restructured UI directory: {ui_path}" + ) + except PermissionError as e: + verbose_proxy_logger.exception( + f"Permission error while restructuring UI directory {ui_path}: {e}" + ) + except Exception as e: + verbose_proxy_logger.exception( + f"Error while restructuring UI directory {ui_path}: {e}" ) except Exception: diff --git a/tests/test_litellm/proxy/test_proxy_server.py b/tests/test_litellm/proxy/test_proxy_server.py index dc0dec3437f..5c7ece04513 100644 --- a/tests/test_litellm/proxy/test_proxy_server.py +++ b/tests/test_litellm/proxy/test_proxy_server.py @@ -275,7 +275,7 @@ def test_sso_key_generate_shows_deprecation_banner(client_no_auth, monkeypatch): def test_restructure_ui_html_files_handles_nested_routes(tmp_path): """ Test that _restructure_ui_html_files correctly restructures HTML files. - Note: This function is only called when is_non_root is True (ui_path != packaged_ui_path). + Note: This function is always called now, both in development and non-root Docker environments. """ from litellm.proxy import proxy_server @@ -312,7 +312,7 @@ def test_restructure_ui_html_files_handles_nested_routes(tmp_path): def test_ui_extensionless_route_requires_restructure(tmp_path): """ Regression for non-root fallback: /ui/login expects login/index.html. - Note: Restructuring only happens when is_non_root is True (ui_path != packaged_ui_path). + Note: Restructuring always happens now, both in development and non-root Docker environments. """ from litellm.proxy import proxy_server @@ -338,12 +338,13 @@ def test_ui_extensionless_route_requires_restructure(tmp_path): assert "login" in response.text -def test_restructure_only_happens_when_non_root(monkeypatch): +def test_restructure_always_happens(monkeypatch): """ - Test that restructuring logic only executes when LITELLM_NON_ROOT is true. - When is_non_root is False, ui_path == packaged_ui_path, so restructuring is skipped. + Test that restructuring logic always executes regardless of LITELLM_NON_ROOT setting. + In development (is_non_root=False), restructuring happens directly in _experimental/out. + In non-root Docker (is_non_root=True), restructuring happens in /var/lib/litellm/ui. """ - # Test Case 1: is_non_root is True - ui_path != packaged_ui_path, so restructuring should happen + # Test Case 1: is_non_root is True - restructuring happens in /var/lib/litellm/ui monkeypatch.setenv("LITELLM_NON_ROOT", "true") runtime_ui_path = "/var/lib/litellm/ui" @@ -356,14 +357,14 @@ def test_restructure_only_happens_when_non_root(monkeypatch): else: ui_path = packaged_ui_path - # This is the condition that determines if restructuring happens - should_restructure = ui_path != packaged_ui_path + # Restructuring always happens now, regardless of ui_path vs packaged_ui_path + should_restructure = True assert is_non_root is True assert should_restructure is True assert ui_path == runtime_ui_path - # Test Case 2: is_non_root is False - ui_path == packaged_ui_path, so restructuring should NOT happen + # Test Case 2: is_non_root is False - restructuring happens directly in packaged_ui_path monkeypatch.delenv("LITELLM_NON_ROOT", raising=False) # Simulate the logic from proxy_server.py @@ -373,11 +374,11 @@ def test_restructure_only_happens_when_non_root(monkeypatch): else: ui_path = packaged_ui_path - # This is the condition that determines if restructuring happens - should_restructure = ui_path != packaged_ui_path + # Restructuring always happens now, even when ui_path == packaged_ui_path + should_restructure = True assert is_non_root is False - assert should_restructure is False + assert should_restructure is True assert ui_path == packaged_ui_path