"""What's on screen right now — the active window's title, and whether something is running fullscreen. Two consumers: * annotate() tacks the focused window's title onto what you said, so "what's this error?" has a referent without you describing it (the desk API takes text only, so this is a text annotation — no screenshot upload). * is_fullscreen_active() feeds do-not-disturb: the pet shouldn't announce anything over a call or a fullscreen game. Everything here is best-effort and must never raise: on a locked-down Wayland session none of it is available, and the correct behaviour is simply "no context", not a crashed pipeline. The subprocess *parsing* is split into pure functions so it can be tested without a display server. """ from __future__ import annotations import platform import re import shutil import subprocess from typing import Optional _TIMEOUT = 2.0 _MAX_TITLE_CHARS = 160 # Titles that are just the desktop itself — annotating with these is noise. _BORING_TITLES = {"", "desktop", "@!0,0;bdib", "plasmashell", "gnome-shell", "xfdesktop"} def _run(args: list[str]) -> Optional[str]: try: completed = subprocess.run(args, capture_output=True, text=True, timeout=_TIMEOUT) except Exception: return None if completed.returncode != 0: return None return completed.stdout # ── pure parsing helpers (unit tested; no display server needed) ───────────── def parse_xprop_window_id(output: str) -> Optional[str]: """`xprop -root _NET_ACTIVE_WINDOW` -> '_NET_ACTIVE_WINDOW(WINDOW): window id # 0x3c00007'""" match = re.search(r"(0x[0-9a-fA-F]+)", output or "") if not match or int(match.group(1), 16) == 0: return None return match.group(1) def parse_xprop_window_name(output: str) -> Optional[str]: """`xprop -id _NET_WM_NAME` -> '_NET_WM_NAME(UTF8_STRING) = "Firefox"'""" match = re.search(r'=\s*"(.*)"\s*$', (output or "").strip(), re.DOTALL) if not match: return None return match.group(1).strip() def parse_xprop_fullscreen(output: str) -> bool: return "_NET_WM_STATE_FULLSCREEN" in (output or "") def clean_title(title: Optional[str]) -> Optional[str]: title = (title or "").strip().replace("\n", " ") if title.lower() in _BORING_TITLES: return None if len(title) > _MAX_TITLE_CHARS: title = title[: _MAX_TITLE_CHARS - 1].rstrip() + "…" return title or None def annotate(text: str, title: Optional[str]) -> str: """Attach the window title as an explicit aside rather than splicing it into the sentence, so the model can ignore it when it's irrelevant.""" text = (text or "").strip() title = clean_title(title) if not text or not title: return text return f"{text}\n\n[on screen right now: {title}]" # ── platform probes ────────────────────────────────────────────────────────── def _linux_active_window_id() -> Optional[str]: if not shutil.which("xprop"): return None output = _run(["xprop", "-root", "_NET_ACTIVE_WINDOW"]) return parse_xprop_window_id(output or "") def _linux_title() -> Optional[str]: if shutil.which("xdotool"): output = _run(["xdotool", "getactivewindow", "getwindowname"]) if output and output.strip(): return output.strip() window_id = _linux_active_window_id() if window_id is None: return None for prop in ("_NET_WM_NAME", "WM_NAME"): output = _run(["xprop", "-id", window_id, prop]) title = parse_xprop_window_name(output or "") if title: return title return None def _windows_title() -> Optional[str]: try: import ctypes user32 = ctypes.windll.user32 handle = user32.GetForegroundWindow() if not handle: return None length = user32.GetWindowTextLengthW(handle) buffer = ctypes.create_unicode_buffer(length + 1) user32.GetWindowTextW(handle, buffer, length + 1) return buffer.value or None except Exception: return None def _macos_title() -> Optional[str]: script = ( 'tell application "System Events" to get name of first application process ' "whose frontmost is true" ) output = _run(["osascript", "-e", script]) return (output or "").strip() or None def active_window_title() -> Optional[str]: """Focused window's title, or None if the platform won't tell us.""" try: system = platform.system() if system == "Linux": return clean_title(_linux_title()) if system == "Windows": return clean_title(_windows_title()) if system == "Darwin": return clean_title(_macos_title()) except Exception: pass return None def is_fullscreen_active() -> bool: """True when the focused window is fullscreen (call, game, presentation). False whenever we can't tell — do-not-disturb should be something you opt into, not something a failed probe turns on.""" try: system = platform.system() if system == "Linux": window_id = _linux_active_window_id() if window_id is None: return False return parse_xprop_fullscreen(_run(["xprop", "-id", window_id, "_NET_WM_STATE"]) or "") if system == "Windows": import ctypes from ctypes import wintypes user32 = ctypes.windll.user32 handle = user32.GetForegroundWindow() if not handle: return False rect = wintypes.RECT() user32.GetWindowRect(handle, ctypes.byref(rect)) screen_w = user32.GetSystemMetrics(0) screen_h = user32.GetSystemMetrics(1) return (rect.right - rect.left) >= screen_w and (rect.bottom - rect.top) >= screen_h except Exception: pass return False def context_for(text: str) -> str: """What the controller sends: *text* plus the active window title, when SCREEN_CONTEXT is on and there's a title worth mentioning.""" from . import config if not config.SCREEN_CONTEXT: return text return annotate(text, active_window_title())