"""Session-level interaction state. No domain, so it lives in core (D-263). One question, asked in one place: **may this invocation prompt?** The answer is not just a flag, because the flag alone is not safe. A prompt with no TTY does not wait for an answer — it *crashes*, which is the recorded `tea` failure in this repo (interactive prompts die in Claude Code, no terminal). So `can_prompt()` requires both an interactive stream and the absence of `--no-input`. Hooks and agents pass `--no-input` explicitly, and would be protected by the TTY check even if they forgot. Nothing prompts today. This exists so that the first thing that wants to has an obvious correct answer available, rather than inventing its own `isatty` check that gets it half right. """ from __future__ import annotations import sys _no_input = False def set_no_input(value: bool) -> None: """Record the `--no-input` flag for this invocation.""" global _no_input _no_input = value def no_input() -> bool: """True when the caller has forbidden prompting.""" return _no_input def can_prompt() -> bool: """True only when prompting is both permitted AND possible. Check this, never `isatty` alone and never the flag alone — the two guard different failures. The flag is a caller's instruction; the TTY check is what stops a prompt from crashing a hook that forgot to pass it. """ if _no_input: return False try: return sys.stdin.isatty() and sys.stderr.isatty() except (AttributeError, ValueError): return False