fix(terminal): strip provider env vars from background and PTY subprocesses (#1172)

* fix: Home Assistant event filtering now closed by default

Previously, when no watch_domains or watch_entities were configured,
ALL state_changed events passed through to the agent, causing users
to be flooded with notifications for every HA entity change.

Now events are dropped by default unless the user explicitly configures:
- watch_domains: list of domains to monitor (e.g. climate, light)
- watch_entities: list of specific entity IDs to monitor
- watch_all: true (new option — opt-in to receive all events)

A warning is logged at connect time if no filters are configured,
guiding users to set up their HA platform config.

All 49 gateway HA tests + 52 HA tool tests pass.

* docs: update Home Assistant integration documentation

- homeassistant.md: Fix event filtering docs to reflect closed-by-default
  behavior. Add watch_all option. Replace Python dict config example with
  YAML. Fix defaults table (was incorrectly showing 'all'). Add required
  configuration warning admonition.
- environment-variables.md: Add HASS_TOKEN and HASS_URL to Messaging section.
- messaging/index.md: Add Home Assistant to description, architecture
  diagram, platform toolsets table, and Next Steps links.

* fix(terminal): strip provider env vars from background and PTY subprocesses

Extends the env var blocklist from #1157 to also cover the two remaining
leaky paths in process_registry.py:

- spawn_local() PTY path (line 156)
- spawn_local() background Popen path (line 197)

Both were still using raw os.environ, leaking provider vars to background
processes and interactive PTY sessions. Now uses the same dynamic
_HERMES_PROVIDER_ENV_BLOCKLIST from local.py.

Explicit env_vars passed to spawn_local() still override the blocklist,
matching the existing behavior for callers that intentionally need these.

Gap identified by PR #1004 (@PeterFile).
This commit is contained in:
Teknium 2026-03-13 07:54:46 -07:00 committed by GitHub
parent c92507e53d
commit 646b4ec533
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -42,7 +42,7 @@ import time
import uuid import uuid
_IS_WINDOWS = platform.system() == "Windows" _IS_WINDOWS = platform.system() == "Windows"
from tools.environments.local import _find_shell from tools.environments.local import _find_shell, _HERMES_PROVIDER_ENV_BLOCKLIST
from dataclasses import dataclass, field from dataclasses import dataclass, field
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
@ -153,7 +153,9 @@ class ProcessRegistry:
else: else:
from ptyprocess import PtyProcess as _PtyProcessCls from ptyprocess import PtyProcess as _PtyProcessCls
user_shell = _find_shell() user_shell = _find_shell()
pty_env = os.environ | (env_vars or {}) pty_env = {k: v for k, v in os.environ.items()
if k not in _HERMES_PROVIDER_ENV_BLOCKLIST}
pty_env.update(env_vars or {})
pty_env["PYTHONUNBUFFERED"] = "1" pty_env["PYTHONUNBUFFERED"] = "1"
pty_proc = _PtyProcessCls.spawn( pty_proc = _PtyProcessCls.spawn(
[user_shell, "-lic", command], [user_shell, "-lic", command],
@ -194,7 +196,9 @@ class ProcessRegistry:
# Force unbuffered output for Python scripts so progress is visible # Force unbuffered output for Python scripts so progress is visible
# during background execution (libraries like tqdm/datasets buffer when # during background execution (libraries like tqdm/datasets buffer when
# stdout is a pipe, hiding output from process(action="poll")). # stdout is a pipe, hiding output from process(action="poll")).
bg_env = os.environ | (env_vars or {}) bg_env = {k: v for k, v in os.environ.items()
if k not in _HERMES_PROVIDER_ENV_BLOCKLIST}
bg_env.update(env_vars or {})
bg_env["PYTHONUNBUFFERED"] = "1" bg_env["PYTHONUNBUFFERED"] = "1"
proc = subprocess.Popen( proc = subprocess.Popen(
[user_shell, "-lic", command], [user_shell, "-lic", command],