diff --git a/hermes_cli/gateway.py b/hermes_cli/gateway.py index 82689f8ff..9e215ff2e 100644 --- a/hermes_cli/gateway.py +++ b/hermes_cli/gateway.py @@ -39,7 +39,7 @@ def _get_service_pids() -> set: pids: set = set() # --- systemd (Linux): user and system scopes --- - if is_linux(): + if supports_systemd_services(): for scope_args in [["systemctl", "--user"], ["systemctl"]]: try: result = subprocess.run( @@ -225,6 +225,16 @@ def stop_profile_gateway() -> bool: def is_linux() -> bool: return sys.platform.startswith('linux') + +def is_termux() -> bool: + prefix = os.getenv("PREFIX", "") + return bool(os.getenv("TERMUX_VERSION") or "com.termux/files/usr" in prefix) + + +def supports_systemd_services() -> bool: + return is_linux() and not is_termux() + + def is_macos() -> bool: return sys.platform == 'darwin' @@ -477,13 +487,15 @@ def install_linux_gateway_from_setup(force: bool = False) -> tuple[str | None, b def get_systemd_linger_status() -> tuple[bool | None, str]: - """Return whether systemd user lingering is enabled for the current user. + """Return systemd linger status for the current user. Returns: (True, "") when linger is enabled. (False, "") when linger is disabled. (None, detail) when the status could not be determined. """ + if is_termux(): + return None, "not supported in Termux" if not is_linux(): return None, "not supported on this platform" @@ -766,7 +778,7 @@ def _print_linger_enable_warning(username: str, detail: str | None = None) -> No def _ensure_linger_enabled() -> None: """Enable linger when possible so the user gateway survives logout.""" - if not is_linux(): + if is_termux() or not is_linux(): return import getpass @@ -1801,7 +1813,7 @@ def _setup_whatsapp(): def _is_service_installed() -> bool: """Check if the gateway is installed as a system service.""" - if is_linux(): + if supports_systemd_services(): return get_systemd_unit_path(system=False).exists() or get_systemd_unit_path(system=True).exists() elif is_macos(): return get_launchd_plist_path().exists() @@ -1810,7 +1822,7 @@ def _is_service_installed() -> bool: def _is_service_running() -> bool: """Check if the gateway service is currently running.""" - if is_linux(): + if supports_systemd_services(): user_unit_exists = get_systemd_unit_path(system=False).exists() system_unit_exists = get_systemd_unit_path(system=True).exists() @@ -1983,7 +1995,7 @@ def gateway_setup(): service_installed = _is_service_installed() service_running = _is_service_running() - if is_linux() and has_conflicting_systemd_units(): + if supports_systemd_services() and has_conflicting_systemd_units(): print_systemd_scope_conflict_warning() print() @@ -1993,7 +2005,7 @@ def gateway_setup(): print_warning("Gateway service is installed but not running.") if prompt_yes_no(" Start it now?", True): try: - if is_linux(): + if supports_systemd_services(): systemd_start() elif is_macos(): launchd_start() @@ -2044,7 +2056,7 @@ def gateway_setup(): if service_running: if prompt_yes_no(" Restart the gateway to pick up changes?", True): try: - if is_linux(): + if supports_systemd_services(): systemd_restart() elif is_macos(): launchd_restart() @@ -2056,7 +2068,7 @@ def gateway_setup(): elif service_installed: if prompt_yes_no(" Start the gateway service?", True): try: - if is_linux(): + if supports_systemd_services(): systemd_start() elif is_macos(): launchd_start() @@ -2064,13 +2076,13 @@ def gateway_setup(): print_error(f" Start failed: {e}") else: print() - if is_linux() or is_macos(): - platform_name = "systemd" if is_linux() else "launchd" + if supports_systemd_services() or is_macos(): + platform_name = "systemd" if supports_systemd_services() else "launchd" if prompt_yes_no(f" Install the gateway as a {platform_name} service? (runs in background, starts on boot)", True): try: installed_scope = None did_install = False - if is_linux(): + if supports_systemd_services(): installed_scope, did_install = install_linux_gateway_from_setup(force=False) else: launchd_install(force=False) @@ -2078,7 +2090,7 @@ def gateway_setup(): print() if did_install and prompt_yes_no(" Start the service now?", True): try: - if is_linux(): + if supports_systemd_services(): systemd_start(system=installed_scope == "system") else: launchd_start() @@ -2089,12 +2101,18 @@ def gateway_setup(): print_info(" You can try manually: hermes gateway install") else: print_info(" You can install later: hermes gateway install") - if is_linux(): + if supports_systemd_services(): print_info(" Or as a boot-time service: sudo hermes gateway install --system") print_info(" Or run in foreground: hermes gateway") else: - print_info(" Service install not supported on this platform.") - print_info(" Run in foreground: hermes gateway") + if is_termux(): + from hermes_constants import display_hermes_home as _dhh + print_info(" Termux does not use systemd/launchd services.") + print_info(" Run in foreground: hermes gateway") + print_info(f" Or start it manually in the background (best effort): nohup hermes gateway >{_dhh()}/logs/gateway.log 2>&1 &") + else: + print_info(" Service install not supported on this platform.") + print_info(" Run in foreground: hermes gateway") else: print() print_info("No platforms configured. Run 'hermes gateway setup' when ready.") @@ -2130,7 +2148,11 @@ def gateway_command(args): force = getattr(args, 'force', False) system = getattr(args, 'system', False) run_as_user = getattr(args, 'run_as_user', None) - if is_linux(): + if is_termux(): + print("Gateway service installation is not supported on Termux.") + print("Run manually: hermes gateway") + sys.exit(1) + if supports_systemd_services(): systemd_install(force=force, system=system, run_as_user=run_as_user) elif is_macos(): launchd_install(force) @@ -2144,7 +2166,11 @@ def gateway_command(args): managed_error("uninstall gateway service (managed by NixOS)") return system = getattr(args, 'system', False) - if is_linux(): + if is_termux(): + print("Gateway service uninstall is not supported on Termux because there is no managed service to remove.") + print("Stop manual runs with: hermes gateway stop") + sys.exit(1) + if supports_systemd_services(): systemd_uninstall(system=system) elif is_macos(): launchd_uninstall() @@ -2154,7 +2180,11 @@ def gateway_command(args): elif subcmd == "start": system = getattr(args, 'system', False) - if is_linux(): + if is_termux(): + print("Gateway service start is not supported on Termux because there is no system service manager.") + print("Run manually: hermes gateway") + sys.exit(1) + if supports_systemd_services(): systemd_start(system=system) elif is_macos(): launchd_start() @@ -2169,7 +2199,7 @@ def gateway_command(args): if stop_all: # --all: kill every gateway process on the machine service_available = False - if is_linux() and (get_systemd_unit_path(system=False).exists() or get_systemd_unit_path(system=True).exists()): + if supports_systemd_services() and (get_systemd_unit_path(system=False).exists() or get_systemd_unit_path(system=True).exists()): try: systemd_stop(system=system) service_available = True @@ -2190,7 +2220,7 @@ def gateway_command(args): else: # Default: stop only the current profile's gateway service_available = False - if is_linux() and (get_systemd_unit_path(system=False).exists() or get_systemd_unit_path(system=True).exists()): + if supports_systemd_services() and (get_systemd_unit_path(system=False).exists() or get_systemd_unit_path(system=True).exists()): try: systemd_stop(system=system) service_available = True @@ -2218,7 +2248,7 @@ def gateway_command(args): system = getattr(args, 'system', False) service_configured = False - if is_linux() and (get_systemd_unit_path(system=False).exists() or get_systemd_unit_path(system=True).exists()): + if supports_systemd_services() and (get_systemd_unit_path(system=False).exists() or get_systemd_unit_path(system=True).exists()): service_configured = True try: systemd_restart(system=system) @@ -2235,7 +2265,7 @@ def gateway_command(args): if not service_available: # systemd/launchd restart failed — check if linger is the issue - if is_linux(): + if supports_systemd_services(): linger_ok, _detail = get_systemd_linger_status() if linger_ok is not True: import getpass @@ -2272,7 +2302,7 @@ def gateway_command(args): system = getattr(args, 'system', False) # Check for service first - if is_linux() and (get_systemd_unit_path(system=False).exists() or get_systemd_unit_path(system=True).exists()): + if supports_systemd_services() and (get_systemd_unit_path(system=False).exists() or get_systemd_unit_path(system=True).exists()): systemd_status(deep, system=system) elif is_macos() and get_launchd_plist_path().exists(): launchd_status(deep) @@ -2289,9 +2319,13 @@ def gateway_command(args): for line in runtime_lines: print(f" {line}") print() - print("To install as a service:") - print(" hermes gateway install") - print(" sudo hermes gateway install --system") + if is_termux(): + print("Termux note:") + print(" Android may stop background jobs when Termux is suspended") + else: + print("To install as a service:") + print(" hermes gateway install") + print(" sudo hermes gateway install --system") else: print("✗ Gateway is not running") runtime_lines = _runtime_health_lines() @@ -2303,5 +2337,8 @@ def gateway_command(args): print() print("To start:") print(" hermes gateway # Run in foreground") - print(" hermes gateway install # Install as user service") - print(" sudo hermes gateway install --system # Install as boot-time system service") + if is_termux(): + print(" nohup hermes gateway > ~/.hermes/logs/gateway.log 2>&1 & # Best-effort background start") + else: + print(" hermes gateway install # Install as user service") + print(" sudo hermes gateway install --system # Install as boot-time system service") diff --git a/hermes_cli/main.py b/hermes_cli/main.py index 1e7be0543..5a6e58672 100644 --- a/hermes_cli/main.py +++ b/hermes_cli/main.py @@ -3763,7 +3763,7 @@ def cmd_update(args): # running gateway needs restarting to pick up the new code. try: from hermes_cli.gateway import ( - is_macos, is_linux, _ensure_user_systemd_env, + is_macos, supports_systemd_services, _ensure_user_systemd_env, find_gateway_pids, _get_service_pids, ) @@ -3774,7 +3774,7 @@ def cmd_update(args): # --- Systemd services (Linux) --- # Discover all hermes-gateway* units (default + profiles) - if is_linux(): + if supports_systemd_services(): try: _ensure_user_systemd_env() except Exception: diff --git a/hermes_cli/uninstall.py b/hermes_cli/uninstall.py index fa49e3c92..7ab154afe 100644 --- a/hermes_cli/uninstall.py +++ b/hermes_cli/uninstall.py @@ -122,6 +122,10 @@ def uninstall_gateway_service(): if platform.system() != "Linux": return False + + prefix = os.getenv("PREFIX", "") + if os.getenv("TERMUX_VERSION") or "com.termux/files/usr" in prefix: + return False try: from hermes_cli.gateway import get_service_name diff --git a/tests/hermes_cli/test_gateway.py b/tests/hermes_cli/test_gateway.py index 11c213635..885597e3e 100644 --- a/tests/hermes_cli/test_gateway.py +++ b/tests/hermes_cli/test_gateway.py @@ -10,6 +10,7 @@ import hermes_cli.gateway as gateway class TestSystemdLingerStatus: def test_reports_enabled(self, monkeypatch): monkeypatch.setattr(gateway, "is_linux", lambda: True) + monkeypatch.setattr(gateway, "is_termux", lambda: False) monkeypatch.setenv("USER", "alice") monkeypatch.setattr( gateway.subprocess, @@ -22,6 +23,7 @@ class TestSystemdLingerStatus: def test_reports_disabled(self, monkeypatch): monkeypatch.setattr(gateway, "is_linux", lambda: True) + monkeypatch.setattr(gateway, "is_termux", lambda: False) monkeypatch.setenv("USER", "alice") monkeypatch.setattr( gateway.subprocess, @@ -32,6 +34,11 @@ class TestSystemdLingerStatus: assert gateway.get_systemd_linger_status() == (False, "") + def test_reports_termux_as_not_supported(self, monkeypatch): + monkeypatch.setattr(gateway, "is_termux", lambda: True) + + assert gateway.get_systemd_linger_status() == (None, "not supported in Termux") + def test_systemd_status_warns_when_linger_disabled(monkeypatch, tmp_path, capsys): unit_path = tmp_path / "hermes-gateway.service" diff --git a/tests/hermes_cli/test_gateway_linger.py b/tests/hermes_cli/test_gateway_linger.py index 3dacea66e..90f8ea3d7 100644 --- a/tests/hermes_cli/test_gateway_linger.py +++ b/tests/hermes_cli/test_gateway_linger.py @@ -8,6 +8,7 @@ import hermes_cli.gateway as gateway class TestEnsureLingerEnabled: def test_linger_already_enabled_via_file(self, monkeypatch, capsys): monkeypatch.setattr(gateway, "is_linux", lambda: True) + monkeypatch.setattr(gateway, "is_termux", lambda: False) monkeypatch.setattr("getpass.getuser", lambda: "testuser") monkeypatch.setattr(gateway, "Path", lambda _path: SimpleNamespace(exists=lambda: True)) @@ -22,6 +23,7 @@ class TestEnsureLingerEnabled: def test_status_enabled_skips_enable(self, monkeypatch, capsys): monkeypatch.setattr(gateway, "is_linux", lambda: True) + monkeypatch.setattr(gateway, "is_termux", lambda: False) monkeypatch.setattr("getpass.getuser", lambda: "testuser") monkeypatch.setattr(gateway, "Path", lambda _path: SimpleNamespace(exists=lambda: False)) monkeypatch.setattr(gateway, "get_systemd_linger_status", lambda: (True, "")) @@ -37,6 +39,7 @@ class TestEnsureLingerEnabled: def test_loginctl_success_enables_linger(self, monkeypatch, capsys): monkeypatch.setattr(gateway, "is_linux", lambda: True) + monkeypatch.setattr(gateway, "is_termux", lambda: False) monkeypatch.setattr("getpass.getuser", lambda: "testuser") monkeypatch.setattr(gateway, "Path", lambda _path: SimpleNamespace(exists=lambda: False)) monkeypatch.setattr(gateway, "get_systemd_linger_status", lambda: (False, "")) @@ -59,6 +62,7 @@ class TestEnsureLingerEnabled: def test_missing_loginctl_shows_manual_guidance(self, monkeypatch, capsys): monkeypatch.setattr(gateway, "is_linux", lambda: True) + monkeypatch.setattr(gateway, "is_termux", lambda: False) monkeypatch.setattr("getpass.getuser", lambda: "testuser") monkeypatch.setattr(gateway, "Path", lambda _path: SimpleNamespace(exists=lambda: False)) monkeypatch.setattr(gateway, "get_systemd_linger_status", lambda: (None, "loginctl not found")) @@ -76,6 +80,7 @@ class TestEnsureLingerEnabled: def test_loginctl_failure_shows_manual_guidance(self, monkeypatch, capsys): monkeypatch.setattr(gateway, "is_linux", lambda: True) + monkeypatch.setattr(gateway, "is_termux", lambda: False) monkeypatch.setattr("getpass.getuser", lambda: "testuser") monkeypatch.setattr(gateway, "Path", lambda _path: SimpleNamespace(exists=lambda: False)) monkeypatch.setattr(gateway, "get_systemd_linger_status", lambda: (False, "")) diff --git a/tests/hermes_cli/test_gateway_service.py b/tests/hermes_cli/test_gateway_service.py index 739d45003..aa21793ae 100644 --- a/tests/hermes_cli/test_gateway_service.py +++ b/tests/hermes_cli/test_gateway_service.py @@ -109,7 +109,8 @@ class TestGatewayStopCleanup: unit_path = tmp_path / "hermes-gateway.service" unit_path.write_text("unit\n", encoding="utf-8") - monkeypatch.setattr(gateway_cli, "is_linux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) monkeypatch.setattr(gateway_cli, "get_systemd_unit_path", lambda system=False: unit_path) @@ -134,7 +135,8 @@ class TestGatewayStopCleanup: unit_path = tmp_path / "hermes-gateway.service" unit_path.write_text("unit\n", encoding="utf-8") - monkeypatch.setattr(gateway_cli, "is_linux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) monkeypatch.setattr(gateway_cli, "get_systemd_unit_path", lambda system=False: unit_path) @@ -256,7 +258,8 @@ class TestGatewayServiceDetection: user_unit = SimpleNamespace(exists=lambda: True) system_unit = SimpleNamespace(exists=lambda: True) - monkeypatch.setattr(gateway_cli, "is_linux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) monkeypatch.setattr( gateway_cli, @@ -278,7 +281,8 @@ class TestGatewayServiceDetection: class TestGatewaySystemServiceRouting: def test_gateway_install_passes_system_flags(self, monkeypatch): - monkeypatch.setattr(gateway_cli, "is_linux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) calls = [] @@ -294,11 +298,30 @@ class TestGatewaySystemServiceRouting: assert calls == [(True, True, "alice")] + def test_gateway_install_reports_termux_manual_mode(self, monkeypatch, capsys): + monkeypatch.setattr(gateway_cli, "is_termux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: False) + monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) + + try: + gateway_cli.gateway_command( + SimpleNamespace(gateway_command="install", force=False, system=False, run_as_user=None) + ) + except SystemExit as exc: + assert exc.code == 1 + else: + raise AssertionError("Expected gateway_command to exit on unsupported Termux service install") + + out = capsys.readouterr().out + assert "not supported on Termux" in out + assert "Run manually: hermes gateway" in out + def test_gateway_status_prefers_system_service_when_only_system_unit_exists(self, monkeypatch): user_unit = SimpleNamespace(exists=lambda: False) system_unit = SimpleNamespace(exists=lambda: True) - monkeypatch.setattr(gateway_cli, "is_linux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) monkeypatch.setattr( gateway_cli, @@ -313,6 +336,20 @@ class TestGatewaySystemServiceRouting: assert calls == [(False, False)] + def test_gateway_status_on_termux_shows_manual_guidance(self, monkeypatch, capsys): + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: False) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: True) + monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) + monkeypatch.setattr(gateway_cli, "find_gateway_pids", lambda exclude_pids=None: []) + monkeypatch.setattr(gateway_cli, "_runtime_health_lines", lambda: []) + + gateway_cli.gateway_command(SimpleNamespace(gateway_command="status", deep=False, system=False)) + + out = capsys.readouterr().out + assert "Gateway is not running" in out + assert "nohup hermes gateway" in out + assert "install as user service" not in out + def test_gateway_restart_does_not_fallback_to_foreground_when_launchd_restart_fails(self, tmp_path, monkeypatch): plist_path = tmp_path / "ai.hermes.gateway.plist" plist_path.write_text("plist\n", encoding="utf-8") @@ -513,12 +550,22 @@ class TestGeneratedUnitUsesDetectedVenv: class TestGeneratedUnitIncludesLocalBin: """~/.local/bin must be in PATH so uvx/pipx tools are discoverable.""" - def test_user_unit_includes_local_bin_in_path(self): + def test_user_unit_includes_local_bin_in_path(self, monkeypatch): + home = Path.home() + monkeypatch.setattr( + gateway_cli, + "_build_user_local_paths", + lambda home_path, existing: [str(home / ".local" / "bin")], + ) unit = gateway_cli.generate_systemd_unit(system=False) - home = str(Path.home()) assert f"{home}/.local/bin" in unit - def test_system_unit_includes_local_bin_in_path(self): + def test_system_unit_includes_local_bin_in_path(self, monkeypatch): + monkeypatch.setattr( + gateway_cli, + "_build_user_local_paths", + lambda home_path, existing: [str(home_path / ".local" / "bin")], + ) unit = gateway_cli.generate_systemd_unit(system=True) # System unit uses the resolved home dir from _system_service_identity assert "/.local/bin" in unit diff --git a/tests/hermes_cli/test_update_gateway_restart.py b/tests/hermes_cli/test_update_gateway_restart.py index e4c8e9227..ceb05f65c 100644 --- a/tests/hermes_cli/test_update_gateway_restart.py +++ b/tests/hermes_cli/test_update_gateway_restart.py @@ -368,9 +368,8 @@ class TestCmdUpdateLaunchdRestart: monkeypatch.setattr( gateway_cli, "is_macos", lambda: False, ) - monkeypatch.setattr( - gateway_cli, "is_linux", lambda: True, - ) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) mock_run.side_effect = _make_run_side_effect( commit_count="3", @@ -429,7 +428,8 @@ class TestCmdUpdateSystemService: ): """When user systemd is inactive but a system service exists, restart via system scope.""" monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) - monkeypatch.setattr(gateway_cli, "is_linux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) mock_run.side_effect = _make_run_side_effect( commit_count="3", @@ -458,7 +458,8 @@ class TestCmdUpdateSystemService: ): """When system service restart fails, show the failure message.""" monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) - monkeypatch.setattr(gateway_cli, "is_linux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) mock_run.side_effect = _make_run_side_effect( commit_count="3", @@ -480,7 +481,8 @@ class TestCmdUpdateSystemService: ): """When both user and system services are active, both are restarted.""" monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) - monkeypatch.setattr(gateway_cli, "is_linux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) mock_run.side_effect = _make_run_side_effect( commit_count="3", @@ -563,7 +565,8 @@ class TestServicePidExclusion: ): """After systemd restart, the sweep must exclude the service PID.""" monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) - monkeypatch.setattr(gateway_cli, "is_linux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) SERVICE_PID = 55000 @@ -642,7 +645,8 @@ class TestGetServicePids: """Unit tests for _get_service_pids().""" def test_returns_systemd_main_pid(self, monkeypatch): - monkeypatch.setattr(gateway_cli, "is_linux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) def fake_run(cmd, **kwargs): @@ -691,7 +695,8 @@ class TestGetServicePids: def test_excludes_zero_pid(self, monkeypatch): """systemd returns MainPID=0 for stopped services; skip those.""" - monkeypatch.setattr(gateway_cli, "is_linux", lambda: True) + monkeypatch.setattr(gateway_cli, "supports_systemd_services", lambda: True) + monkeypatch.setattr(gateway_cli, "is_termux", lambda: False) monkeypatch.setattr(gateway_cli, "is_macos", lambda: False) def fake_run(cmd, **kwargs):