mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-08 13:12:08 +00:00
feat(raft): add gateway setup wizard
Add an interactive Raft setup flow for hermes gateway setup. The wizard follows the existing platform adapter setup pattern, persists RAFT_PROFILE to the Hermes env file, preserves an existing profile when the user declines reconfiguration, and registers the flow via setup_fn. Add focused Raft adapter coverage for saving RAFT_PROFILE, keeping an existing profile, and registering setup_fn. Signed-off-by: skyzh <skyzh@mail.build> Signed-off-by: HaoHao <HaoHao@mail.build>
This commit is contained in:
parent
da6d5fcd13
commit
cc7d20d683
2 changed files with 73 additions and 0 deletions
|
|
@ -754,6 +754,48 @@ def _env_enablement() -> Optional[dict]:
|
|||
return {"enabled": True}
|
||||
|
||||
|
||||
def interactive_setup() -> None:
|
||||
"""Interactive ``hermes gateway setup`` flow for the Raft platform.
|
||||
|
||||
Lazy-imports CLI helpers so the plugin stays importable in gateway runtime
|
||||
and test contexts. The flow persists ``RAFT_PROFILE`` to the Hermes env
|
||||
file so the Raft adapter auto-enables after a gateway restart.
|
||||
"""
|
||||
from hermes_cli.cli_output import (
|
||||
print_header,
|
||||
print_info,
|
||||
print_success,
|
||||
print_warning,
|
||||
prompt,
|
||||
prompt_yes_no,
|
||||
)
|
||||
from hermes_cli.config import get_env_value, save_env_value
|
||||
|
||||
print_header("Raft")
|
||||
existing_profile = get_env_value("RAFT_PROFILE")
|
||||
if existing_profile:
|
||||
print_info(f"Raft: already configured (profile: {existing_profile})")
|
||||
if not prompt_yes_no("Reconfigure Raft?", False):
|
||||
print_info(f"Keeping RAFT_PROFILE={existing_profile}.")
|
||||
return
|
||||
|
||||
print_info("Connect Hermes to Raft as an external agent.")
|
||||
print_info("Create the External Agent in Raft first, then run:")
|
||||
print_info(" raft agent login --server <server-url> --agent <agent-id> --profile-slug <slug>")
|
||||
print()
|
||||
|
||||
profile = prompt("Raft profile slug", default=existing_profile or "")
|
||||
if not profile:
|
||||
print_warning("Raft profile slug is required; skipping Raft setup")
|
||||
return
|
||||
|
||||
save_env_value("RAFT_PROFILE", profile.strip())
|
||||
|
||||
print()
|
||||
print_success("Raft configuration saved")
|
||||
print_info("Restart the gateway for changes to take effect: hermes gateway restart")
|
||||
|
||||
|
||||
def register(ctx) -> None:
|
||||
"""Plugin entry point — called by the Hermes plugin system."""
|
||||
ctx.register_platform(
|
||||
|
|
@ -764,6 +806,7 @@ def register(ctx) -> None:
|
|||
is_connected=_is_connected,
|
||||
required_env=["RAFT_PROFILE"],
|
||||
install_hint="Install the Raft CLI from https://raft.build",
|
||||
setup_fn=interactive_setup,
|
||||
env_enablement_fn=_env_enablement,
|
||||
emoji="🔔",
|
||||
platform_hint=(
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ from plugins.platforms.raft.adapter import (
|
|||
_on_session_end,
|
||||
_on_session_finalize,
|
||||
check_raft_requirements,
|
||||
interactive_setup,
|
||||
register,
|
||||
)
|
||||
from gateway.session import build_session_key
|
||||
|
|
@ -425,6 +426,34 @@ class TestRaftConfig:
|
|||
assert _is_connected(PlatformConfig(enabled=True, extra={"enabled": True})) is True
|
||||
assert _is_connected(PlatformConfig(enabled=True, extra={})) is False
|
||||
|
||||
def test_interactive_setup_saves_raft_profile(self, monkeypatch, tmp_path, capsys):
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
monkeypatch.delenv("RAFT_PROFILE", raising=False)
|
||||
monkeypatch.setattr("builtins.input", lambda _prompt: "dev-profile")
|
||||
|
||||
interactive_setup()
|
||||
|
||||
assert (tmp_path / ".env").read_text(encoding="utf-8") == "RAFT_PROFILE=dev-profile\n"
|
||||
assert os.environ["RAFT_PROFILE"] == "dev-profile"
|
||||
out = capsys.readouterr().out
|
||||
assert "Raft configuration saved" in out
|
||||
assert "hermes gateway restart" in out
|
||||
|
||||
def test_interactive_setup_keeps_existing_profile_when_not_reconfigured(
|
||||
self, monkeypatch, tmp_path, capsys
|
||||
):
|
||||
env_path = tmp_path / ".env"
|
||||
env_path.write_text("RAFT_PROFILE=existing\n", encoding="utf-8")
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
monkeypatch.setenv("RAFT_PROFILE", "existing")
|
||||
monkeypatch.setattr("builtins.input", lambda _prompt: "n")
|
||||
|
||||
interactive_setup()
|
||||
|
||||
assert env_path.read_text(encoding="utf-8") == "RAFT_PROFILE=existing\n"
|
||||
assert os.environ["RAFT_PROFILE"] == "existing"
|
||||
assert "Keeping RAFT_PROFILE=existing" in capsys.readouterr().out
|
||||
|
||||
def test_register_calls_register_platform(self):
|
||||
registered = {}
|
||||
hooks = {}
|
||||
|
|
@ -441,6 +470,7 @@ class TestRaftConfig:
|
|||
assert registered["name"] == "raft"
|
||||
assert registered["label"] == "Raft"
|
||||
assert registered["emoji"] == "🔔"
|
||||
assert registered["setup_fn"] is interactive_setup
|
||||
assert "profile show" in registered["platform_hint"]
|
||||
assert "manual get" in registered["platform_hint"]
|
||||
assert "--profile" in registered["platform_hint"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue