fix: follow-up fixes for salvaged PRs

- Fix GatewayApp → GatewayRunner import in api_server.py (PR #4976)
- Update launchd test assertions for new bootstrap/bootout/kickstart commands (PR #4892)
- Add nonlocal message declaration in run_sync() to fix UnboundLocalError (pre-existing scoping bug)
This commit is contained in:
Teknium
2026-04-05 11:46:06 -07:00
committed by Teknium
parent 6a6ae9a5c3
commit 0c95e91059
3 changed files with 21 additions and 13 deletions

View File

@ -423,8 +423,8 @@ class APIServerAdapter(BasePlatformAdapter):
# Load fallback provider chain so the API server platform has the
# same fallback behaviour as Telegram/Discord/Slack (fixes #4954).
from gateway.run import GatewayApp
fallback_model = GatewayApp._load_fallback_model()
from gateway.run import GatewayRunner
fallback_model = GatewayRunner._load_fallback_model()
agent = AIAgent(
model=model,

View File

@ -6233,6 +6233,14 @@ class GatewayRunner:
logger.debug("status_callback error (%s): %s", event_type, _e)
def run_sync():
# The conditional re-assignment of `message` further below
# (prepending model-switch notes) makes Python treat it as a
# local variable in the entire function. `nonlocal` lets us
# read *and* reassign the outer `_run_agent` parameter without
# triggering an UnboundLocalError on the earlier read at
# `_resolve_turn_agent_config(message, …)`.
nonlocal message
# Pass session_key to process registry via env var so background
# processes can be mapped back to this gateway session
os.environ["HERMES_SESSION_KEY"] = session_key or ""

View File

@ -218,9 +218,9 @@ class TestLaunchdPlistRefresh:
assert result is True
# Plist should now contain the generated content (which includes --replace)
assert "--replace" in plist_path.read_text()
# Should have unloaded then reloaded
assert any("unload" in str(c) for c in calls)
assert any("load" in str(c) for c in calls)
# Should have booted out then bootstrapped
assert any("bootout" in str(c) for c in calls)
assert any("bootstrap" in str(c) for c in calls)
def test_refresh_skips_when_current(self, tmp_path, monkeypatch):
plist_path = tmp_path / "ai.hermes.gateway.plist"
@ -262,10 +262,10 @@ class TestLaunchdPlistRefresh:
gateway_cli.launchd_start()
# First calls should be refresh (unload/load), then start
# First calls should be refresh (bootout/bootstrap), then kickstart
cmd_strs = [" ".join(c) for c in calls]
assert any("unload" in s for s in cmd_strs)
assert any("start" in s for s in cmd_strs)
assert any("bootout" in s for s in cmd_strs)
assert any("kickstart" in s for s in cmd_strs)
def test_launchd_start_recreates_missing_plist_and_loads_service(self, tmp_path, monkeypatch):
"""launchd_start self-heals when the plist file is missing entirely."""
@ -288,11 +288,11 @@ class TestLaunchdPlistRefresh:
assert "--replace" in plist_path.read_text()
cmd_strs = [" ".join(c) for c in calls]
# Should load the new plist, then start
assert any("load" in s for s in cmd_strs)
assert any("start" in s for s in cmd_strs)
# Should NOT call unload (nothing to unload)
assert not any("unload" in s for s in cmd_strs)
# Should bootstrap the new plist, then kickstart
assert any("bootstrap" in s for s in cmd_strs)
assert any("kickstart" in s for s in cmd_strs)
# Should NOT call bootout (nothing to bootout)
assert not any("bootout" in s for s in cmd_strs)
class TestCmdUpdateLaunchdRestart: