diff --git a/tests/test_windows_subprocess_no_window_flags.py b/tests/test_windows_subprocess_no_window_flags.py index 7768f5fec08..3777182167e 100644 --- a/tests/test_windows_subprocess_no_window_flags.py +++ b/tests/test_windows_subprocess_no_window_flags.py @@ -300,6 +300,44 @@ def test_local_stt_audio_prep_hides_ffmpeg_window(monkeypatch, tmp_path): assert captured[0][0][0] == "ffmpeg" assert captured[0][1]["creationflags"] == _CREATE_NO_WINDOW +def test_checkpoint_manager_git_hides_windows(monkeypatch): + from tools import checkpoint_manager + + captured = [] + + def fake_run(cmd, **kwargs): + captured.append((cmd, kwargs)) + return _Completed(stdout="clean\n") + + monkeypatch.setattr(checkpoint_manager, "IS_WINDOWS", True) + monkeypatch.setattr(checkpoint_manager, "windows_hide_flags", lambda: _CREATE_NO_WINDOW) + monkeypatch.setattr(checkpoint_manager.subprocess, "run", fake_run) + + ok, _, _ = checkpoint_manager._run_git(["status", "--short"], Path("C:/store"), ".") + assert ok + assert captured[0][0][0] == "git" + assert captured[0][1]["creationflags"] == _CREATE_NO_WINDOW + + +def test_skills_hub_gh_token_hides_windows(monkeypatch): + from tools import skills_hub + + captured = [] + + def fake_run(cmd, **kwargs): + captured.append((cmd, kwargs)) + return _Completed(stdout="gho_from_cli\n") + + monkeypatch.setattr(skills_hub, "IS_WINDOWS", True) + monkeypatch.setattr(skills_hub, "windows_hide_flags", lambda: _CREATE_NO_WINDOW) + monkeypatch.setattr(skills_hub.subprocess, "run", fake_run) + + auth = skills_hub.GitHubAuth.__new__(skills_hub.GitHubAuth) + assert auth._try_gh_cli() == "gho_from_cli" + assert captured[0][0] == ["gh", "auth", "token"] + assert captured[0][1]["creationflags"] == _CREATE_NO_WINDOW + + def test_tui_slash_worker_hides_python_window(monkeypatch): from tui_gateway import server diff --git a/tools/checkpoint_manager.py b/tools/checkpoint_manager.py index 720973b67e0..589c993ba6b 100644 --- a/tools/checkpoint_manager.py +++ b/tools/checkpoint_manager.py @@ -58,6 +58,7 @@ import subprocess import time from pathlib import Path from hermes_constants import get_hermes_home +from hermes_cli._subprocess_compat import IS_WINDOWS, windows_hide_flags from typing import Dict, List, Optional, Set, Tuple from utils import env_int @@ -321,6 +322,10 @@ def _run_git( env = _git_env(store, str(normalized_working_dir), index_file=index_file) cmd = ["git"] + list(args) allowed_returncodes = allowed_returncodes or set() + # Checkpoints run inside the console-less desktop/gateway backend; a bare + # git spawn there pops a fresh conhost window per call (status, add, + # commit, …) on Windows. No-op on POSIX. + _popen_kwargs = {"creationflags": windows_hide_flags()} if IS_WINDOWS else {} try: result = subprocess.run( cmd, @@ -330,6 +335,7 @@ def _run_git( env=env, cwd=str(normalized_working_dir), stdin=subprocess.DEVNULL, + **_popen_kwargs, ) ok = result.returncode == 0 stdout = result.stdout.strip() @@ -450,6 +456,7 @@ def _init_store(store: Path, working_dir: str) -> Optional[str]: capture_output=True, text=True, env=init_env, timeout=_GIT_TIMEOUT, stdin=subprocess.DEVNULL, + **({"creationflags": windows_hide_flags()} if IS_WINDOWS else {}), ) if result.returncode != 0: return f"Shadow store init failed: {result.stderr.strip()}" diff --git a/tools/skills_hub.py b/tools/skills_hub.py index 76969fb8d8c..676b6c81f76 100644 --- a/tools/skills_hub.py +++ b/tools/skills_hub.py @@ -26,6 +26,7 @@ from dataclasses import dataclass, field from datetime import datetime, timezone from pathlib import Path, PurePosixPath from hermes_constants import get_hermes_home +from hermes_cli._subprocess_compat import IS_WINDOWS, windows_hide_flags from agent.skill_utils import is_excluded_skill_path from typing import Any, Dict, List, Optional, Tuple, Union from urllib.parse import urljoin, urlparse, urlunparse @@ -302,6 +303,7 @@ class GitHubAuth: ["gh", "auth", "token"], capture_output=True, text=True, timeout=5, stdin=subprocess.DEVNULL, + **({"creationflags": windows_hide_flags()} if IS_WINDOWS else {}), ) if result.returncode == 0 and result.stdout.strip(): return result.stdout.strip()