mirror of
https://github.com/Minidoracat/mcp-feedback-enhanced.git
synced 2025-07-27 10:42:25 +08:00
✨ 新增 WSL 環境檢測功能,並在相關函數中整合 WSL 支援,提升跨平台使用體驗。更新測試用例以涵蓋新功能。
This commit is contained in:
parent
eb77bf918b
commit
013aadf210
@ -114,42 +114,83 @@ mcp = FastMCP(SERVER_NAME, version=__version__, **fastmcp_settings)
|
||||
|
||||
|
||||
# ===== 工具函數 =====
|
||||
def is_wsl_environment() -> bool:
|
||||
"""
|
||||
檢測是否在 WSL (Windows Subsystem for Linux) 環境中運行
|
||||
|
||||
Returns:
|
||||
bool: True 表示 WSL 環境,False 表示其他環境
|
||||
"""
|
||||
try:
|
||||
# 檢查 /proc/version 文件是否包含 WSL 標識
|
||||
if os.path.exists('/proc/version'):
|
||||
with open('/proc/version', 'r') as f:
|
||||
version_info = f.read().lower()
|
||||
if 'microsoft' in version_info or 'wsl' in version_info:
|
||||
debug_log("偵測到 WSL 環境(通過 /proc/version)")
|
||||
return True
|
||||
|
||||
# 檢查 WSL 相關環境變數
|
||||
wsl_env_vars = ['WSL_DISTRO_NAME', 'WSL_INTEROP', 'WSLENV']
|
||||
for env_var in wsl_env_vars:
|
||||
if os.getenv(env_var):
|
||||
debug_log(f"偵測到 WSL 環境變數: {env_var}")
|
||||
return True
|
||||
|
||||
# 檢查是否存在 WSL 特有的路徑
|
||||
wsl_paths = ['/mnt/c', '/mnt/d', '/proc/sys/fs/binfmt_misc/WSLInterop']
|
||||
for path in wsl_paths:
|
||||
if os.path.exists(path):
|
||||
debug_log(f"偵測到 WSL 特有路徑: {path}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
debug_log(f"WSL 檢測過程中發生錯誤: {e}")
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def is_remote_environment() -> bool:
|
||||
"""
|
||||
檢測是否在遠端環境中運行
|
||||
|
||||
|
||||
Returns:
|
||||
bool: True 表示遠端環境,False 表示本地環境
|
||||
"""
|
||||
# WSL 不應被視為遠端環境,因為它可以訪問 Windows 瀏覽器
|
||||
if is_wsl_environment():
|
||||
debug_log("WSL 環境不被視為遠端環境")
|
||||
return False
|
||||
|
||||
# 檢查 SSH 連線指標
|
||||
for env_var in SSH_ENV_VARS:
|
||||
if os.getenv(env_var):
|
||||
debug_log(f"偵測到 SSH 環境變數: {env_var}")
|
||||
return True
|
||||
|
||||
|
||||
# 檢查遠端開發環境
|
||||
for env_var in REMOTE_ENV_VARS:
|
||||
if os.getenv(env_var):
|
||||
debug_log(f"偵測到遠端開發環境: {env_var}")
|
||||
return True
|
||||
|
||||
|
||||
# 檢查 Docker 容器
|
||||
if os.path.exists('/.dockerenv'):
|
||||
debug_log("偵測到 Docker 容器環境")
|
||||
return True
|
||||
|
||||
|
||||
# Windows 遠端桌面檢查
|
||||
if sys.platform == 'win32':
|
||||
session_name = os.getenv('SESSIONNAME', '')
|
||||
if session_name and 'RDP' in session_name:
|
||||
debug_log(f"偵測到 Windows 遠端桌面: {session_name}")
|
||||
return True
|
||||
|
||||
# Linux 無顯示環境檢查
|
||||
if sys.platform.startswith('linux') and not os.getenv('DISPLAY'):
|
||||
|
||||
# Linux 無顯示環境檢查(但排除 WSL)
|
||||
if sys.platform.startswith('linux') and not os.getenv('DISPLAY') and not is_wsl_environment():
|
||||
debug_log("偵測到 Linux 無顯示環境")
|
||||
return True
|
||||
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@ -567,16 +608,18 @@ async def launch_web_ui_with_timeout(project_dir: str, summary: str, timeout: in
|
||||
def get_system_info() -> str:
|
||||
"""
|
||||
獲取系統環境資訊
|
||||
|
||||
|
||||
Returns:
|
||||
str: JSON 格式的系統資訊
|
||||
"""
|
||||
is_remote = is_remote_environment()
|
||||
is_wsl = is_wsl_environment()
|
||||
can_gui = can_use_gui()
|
||||
|
||||
|
||||
system_info = {
|
||||
"平台": sys.platform,
|
||||
"Python 版本": sys.version.split()[0],
|
||||
"WSL 環境": is_wsl,
|
||||
"遠端環境": is_remote,
|
||||
"GUI 可用": can_gui,
|
||||
"建議介面": "Web UI" if is_remote or not can_gui else "Qt GUI",
|
||||
@ -586,9 +629,12 @@ def get_system_info() -> str:
|
||||
"DISPLAY": os.getenv("DISPLAY"),
|
||||
"VSCODE_INJECTION": os.getenv("VSCODE_INJECTION"),
|
||||
"SESSIONNAME": os.getenv("SESSIONNAME"),
|
||||
"WSL_DISTRO_NAME": os.getenv("WSL_DISTRO_NAME"),
|
||||
"WSL_INTEROP": os.getenv("WSL_INTEROP"),
|
||||
"WSLENV": os.getenv("WSLENV"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return json.dumps(system_info, ensure_ascii=False, indent=2)
|
||||
|
||||
|
||||
|
@ -162,23 +162,27 @@ def test_environment_detection():
|
||||
"""Test environment detection logic"""
|
||||
debug_log("🔍 測試環境檢測功能")
|
||||
debug_log("-" * 30)
|
||||
|
||||
|
||||
try:
|
||||
from .server import is_remote_environment, can_use_gui
|
||||
|
||||
from .server import is_remote_environment, is_wsl_environment, can_use_gui
|
||||
|
||||
wsl_detected = is_wsl_environment()
|
||||
remote_detected = is_remote_environment()
|
||||
gui_available = can_use_gui()
|
||||
|
||||
|
||||
debug_log(f"WSL 環境檢測: {'是' if wsl_detected else '否'}")
|
||||
debug_log(f"遠端環境檢測: {'是' if remote_detected else '否'}")
|
||||
debug_log(f"GUI 可用性: {'是' if gui_available else '否'}")
|
||||
|
||||
if remote_detected:
|
||||
|
||||
if wsl_detected:
|
||||
debug_log("✅ 檢測到 WSL 環境,將使用 Web UI 並支援 Windows 瀏覽器啟動")
|
||||
elif remote_detected:
|
||||
debug_log("✅ 將使用 Web UI (適合遠端開發環境)")
|
||||
else:
|
||||
debug_log("✅ 將使用 Qt GUI (本地環境)")
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
except Exception as e:
|
||||
debug_log(f"❌ 環境檢測失敗: {e}")
|
||||
return False
|
||||
@ -245,27 +249,30 @@ def test_environment_web_ui_mode():
|
||||
"""Test environment-based Web UI mode"""
|
||||
debug_log("\n🌐 測試環境變數控制 Web UI 模式")
|
||||
debug_log("-" * 30)
|
||||
|
||||
|
||||
try:
|
||||
from .server import interactive_feedback, is_remote_environment, can_use_gui
|
||||
from .server import interactive_feedback, is_remote_environment, is_wsl_environment, can_use_gui
|
||||
import os
|
||||
|
||||
|
||||
# 顯示當前環境狀態
|
||||
is_wsl = is_wsl_environment()
|
||||
is_remote = is_remote_environment()
|
||||
gui_available = can_use_gui()
|
||||
force_web_env = os.getenv("FORCE_WEB", "").lower()
|
||||
|
||||
debug_log(f"當前環境 - 遠端: {is_remote}, GUI 可用: {gui_available}")
|
||||
|
||||
debug_log(f"當前環境 - WSL: {is_wsl}, 遠端: {is_remote}, GUI 可用: {gui_available}")
|
||||
debug_log(f"FORCE_WEB 環境變數: {force_web_env or '未設定'}")
|
||||
|
||||
|
||||
if force_web_env in ("true", "1", "yes", "on"):
|
||||
debug_log("✅ FORCE_WEB 已啟用,將強制使用 Web UI")
|
||||
elif is_wsl:
|
||||
debug_log("✅ WSL 環境,將使用 Web UI 並支援 Windows 瀏覽器啟動")
|
||||
elif not is_remote and gui_available:
|
||||
debug_log("ℹ️ 本地 GUI 環境,將使用 Qt GUI")
|
||||
debug_log("💡 可設定 FORCE_WEB=true 強制使用 Web UI 進行測試")
|
||||
else:
|
||||
debug_log("ℹ️ 將自動使用 Web UI(遠端環境或 GUI 不可用)")
|
||||
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
|
@ -4,18 +4,125 @@
|
||||
瀏覽器工具函數
|
||||
==============
|
||||
|
||||
提供瀏覽器相關的工具函數。
|
||||
提供瀏覽器相關的工具函數,包含 WSL 環境的特殊處理。
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import webbrowser
|
||||
from typing import Callable
|
||||
|
||||
# 導入調試功能
|
||||
from ...debug import server_debug_log as debug_log
|
||||
|
||||
|
||||
def is_wsl_environment() -> bool:
|
||||
"""
|
||||
檢測是否在 WSL 環境中運行
|
||||
|
||||
Returns:
|
||||
bool: True 表示 WSL 環境,False 表示其他環境
|
||||
"""
|
||||
try:
|
||||
# 檢查 /proc/version 文件是否包含 WSL 標識
|
||||
if os.path.exists('/proc/version'):
|
||||
with open('/proc/version', 'r') as f:
|
||||
version_info = f.read().lower()
|
||||
if 'microsoft' in version_info or 'wsl' in version_info:
|
||||
return True
|
||||
|
||||
# 檢查 WSL 相關環境變數
|
||||
wsl_env_vars = ['WSL_DISTRO_NAME', 'WSL_INTEROP', 'WSLENV']
|
||||
for env_var in wsl_env_vars:
|
||||
if os.getenv(env_var):
|
||||
return True
|
||||
|
||||
# 檢查是否存在 WSL 特有的路徑
|
||||
wsl_paths = ['/mnt/c', '/mnt/d', '/proc/sys/fs/binfmt_misc/WSLInterop']
|
||||
for path in wsl_paths:
|
||||
if os.path.exists(path):
|
||||
return True
|
||||
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def open_browser_in_wsl(url: str) -> None:
|
||||
"""
|
||||
在 WSL 環境中開啟 Windows 瀏覽器
|
||||
|
||||
Args:
|
||||
url: 要開啟的 URL
|
||||
"""
|
||||
try:
|
||||
# 嘗試使用 cmd.exe 啟動瀏覽器
|
||||
cmd = ['cmd.exe', '/c', 'start', url]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
|
||||
|
||||
if result.returncode == 0:
|
||||
debug_log(f"成功使用 cmd.exe 啟動瀏覽器: {url}")
|
||||
return
|
||||
else:
|
||||
debug_log(f"cmd.exe 啟動失敗,返回碼: {result.returncode}, 錯誤: {result.stderr}")
|
||||
|
||||
except Exception as e:
|
||||
debug_log(f"使用 cmd.exe 啟動瀏覽器失敗: {e}")
|
||||
|
||||
try:
|
||||
# 嘗試使用 powershell.exe 啟動瀏覽器
|
||||
cmd = ['powershell.exe', '-c', f'Start-Process "{url}"']
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
|
||||
|
||||
if result.returncode == 0:
|
||||
debug_log(f"成功使用 powershell.exe 啟動瀏覽器: {url}")
|
||||
return
|
||||
else:
|
||||
debug_log(f"powershell.exe 啟動失敗,返回碼: {result.returncode}, 錯誤: {result.stderr}")
|
||||
|
||||
except Exception as e:
|
||||
debug_log(f"使用 powershell.exe 啟動瀏覽器失敗: {e}")
|
||||
|
||||
try:
|
||||
# 最後嘗試使用 wslview(如果安裝了 wslu 套件)
|
||||
cmd = ['wslview', url]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
|
||||
|
||||
if result.returncode == 0:
|
||||
debug_log(f"成功使用 wslview 啟動瀏覽器: {url}")
|
||||
return
|
||||
else:
|
||||
debug_log(f"wslview 啟動失敗,返回碼: {result.returncode}, 錯誤: {result.stderr}")
|
||||
|
||||
except Exception as e:
|
||||
debug_log(f"使用 wslview 啟動瀏覽器失敗: {e}")
|
||||
|
||||
# 如果所有方法都失敗,拋出異常
|
||||
raise Exception("無法在 WSL 環境中啟動 Windows 瀏覽器")
|
||||
|
||||
|
||||
def smart_browser_open(url: str) -> None:
|
||||
"""
|
||||
智能瀏覽器開啟函數,根據環境選擇最佳方式
|
||||
|
||||
Args:
|
||||
url: 要開啟的 URL
|
||||
"""
|
||||
if is_wsl_environment():
|
||||
debug_log("檢測到 WSL 環境,使用 WSL 專用瀏覽器啟動方式")
|
||||
open_browser_in_wsl(url)
|
||||
else:
|
||||
debug_log("使用標準瀏覽器啟動方式")
|
||||
webbrowser.open(url)
|
||||
|
||||
|
||||
def get_browser_opener() -> Callable[[str], None]:
|
||||
"""
|
||||
獲取瀏覽器開啟函數
|
||||
|
||||
|
||||
Returns:
|
||||
Callable: 瀏覽器開啟函數
|
||||
"""
|
||||
return webbrowser.open
|
||||
return smart_browser_open
|
Loading…
x
Reference in New Issue
Block a user