From a9d7c3912f4a2ee0911dbbb80643c738638d7cd1 Mon Sep 17 00:00:00 2001 From: Noah Qin <105060587+imnotnoahhh@users.noreply.github.com> Date: Thu, 5 Mar 2026 09:35:26 +0800 Subject: [PATCH] fix(sudo): add GUI mode support for non-TTY environments (#536) When Mole is called from GUI applications (e.g., SwiftUI apps), the request_sudo_access() function would fail with '/dev/tty: Device not configured' error because /dev/tty is not available in non-TTY contexts. This commit adds automatic detection of the runtime environment and uses macOS native password dialog (via osascript) when running in GUI mode, while preserving all existing TTY behavior including Touch ID support. Changes: - Detect TTY availability before attempting terminal-based authentication - Use osascript to display native password dialog in GUI mode - Maintain backward compatibility with all terminal-based workflows - Ensure secure password handling (unset after use) Fixes commands like 'mole clean', 'mole optimize', 'mole purge' when invoked from GUI applications. --- lib/core/sudo.sh | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/core/sudo.sh b/lib/core/sudo.sh index fe1fb16..483497d 100644 --- a/lib/core/sudo.sh +++ b/lib/core/sudo.sh @@ -108,14 +108,41 @@ request_sudo_access() { return 0 fi - # Get TTY path + # Detect if running in TTY environment local tty_path="/dev/tty" + local is_gui_mode=false + if [[ ! -r "$tty_path" || ! -w "$tty_path" ]]; then tty_path=$(tty 2> /dev/null || echo "") if [[ -z "$tty_path" || ! -r "$tty_path" || ! -w "$tty_path" ]]; then - log_error "No interactive terminal available" + is_gui_mode=true + fi + fi + + # GUI mode: use osascript for password dialog + if [[ "$is_gui_mode" == true ]]; then + # Clear sudo cache before attempting authentication + sudo -k 2> /dev/null + + # Display native macOS password dialog + local password + password=$(osascript -e "display dialog \"$prompt_msg\" default answer \"\" with title \"Mole\" with icon caution with hidden answer" -e 'text returned of result' 2> /dev/null) + + if [[ -z "$password" ]]; then + # User cancelled the dialog + unset password return 1 fi + + # Attempt sudo authentication with the provided password + if printf '%s\n' "$password" | sudo -S -p "" -v > /dev/null 2>&1; then + unset password + return 0 + fi + + # Password was incorrect + unset password + return 1 fi sudo -k