diff --git a/tools/lazy_deps.py b/tools/lazy_deps.py index 5b5878eb451..02e3038d4d3 100644 --- a/tools/lazy_deps.py +++ b/tools/lazy_deps.py @@ -456,7 +456,23 @@ def ensure(feature: str, *, prompt: bool = True) -> None: "lazy installs disabled (security.allow_lazy_installs=false)" ) - if prompt and sys.stdin.isatty() and sys.stdout.isatty(): + # Only show the interactive confirmation when we own a TTY and + # prompt_toolkit isn't running. A bare input() deadlocks when a + # prompt_toolkit app owns the terminal because keystrokes route to + # its event loop rather than stdin, so the prompt blocks forever. + # Under the TUI we skip the prompt and proceed — lazy installs are + # gated by security.allow_lazy_installs, so reaching here is + # already user opt-in. + _pt_active = False + if "prompt_toolkit.application.current" in sys.modules: + try: + from prompt_toolkit.application.current import get_app_or_none + _app = get_app_or_none() + _pt_active = _app is not None and getattr(_app, "is_running", False) + except Exception: + _pt_active = False + + if prompt and not _pt_active and sys.stdin.isatty() and sys.stdout.isatty(): spec_list = ", ".join(missing) try: answer = input(