mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-18 09:51:59 +00:00
feat(relay): register RelayAdapter through platform registry (flagged off by default)
register_relay_adapter() registers the generic 'relay' platform via the same PlatformRegistry path as plugin adapters — no core dispatch changes. OFF by default (dark-launch): only registers when HERMES_GATEWAY_RELAY is truthy (or force=True for tests), so existing single-tenant/direct deployments are unaffected. Factory builds a transport-less RelayAdapter with a placeholder descriptor; the real descriptor is negotiated at handshake. Phase 1, Task 1.3 of the gateway-relay plan.
This commit is contained in:
parent
259e78e175
commit
d0133fd8e4
2 changed files with 125 additions and 0 deletions
|
|
@ -8,4 +8,74 @@ a deprecation cycle until at least two real Class-1 platforms (Discord +
|
|||
Telegram) have shaken out the schema.
|
||||
|
||||
See ``docs/relay-connector-contract.md`` for the formal cross-repo interface.
|
||||
|
||||
Registration is OFF by default: ``register_relay_adapter()`` only registers the
|
||||
``relay`` platform when the relay feature flag is enabled, so existing
|
||||
single-tenant/direct deployments are completely unaffected (dark-launch posture).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def relay_enabled() -> bool:
|
||||
"""Whether the relay adapter should be registered.
|
||||
|
||||
Off by default. Enabled when ``HERMES_GATEWAY_RELAY=1`` (or true/yes/on).
|
||||
A config-file gate can be layered on later; the env flag is the minimal
|
||||
dark-launch switch so default deployments never register the adapter.
|
||||
"""
|
||||
return os.environ.get("HERMES_GATEWAY_RELAY", "").strip().lower() in (
|
||||
"1",
|
||||
"true",
|
||||
"yes",
|
||||
"on",
|
||||
)
|
||||
|
||||
|
||||
def register_relay_adapter(force: bool = False) -> bool:
|
||||
"""Register the generic ``relay`` platform via the platform registry.
|
||||
|
||||
No-op unless the relay flag is set (or ``force=True`` for tests). Returns
|
||||
True if registration happened. Additive: uses the same registry path as
|
||||
plugin adapters, so no core dispatch changes are needed.
|
||||
|
||||
The factory builds a transport-less ``RelayAdapter`` with a placeholder
|
||||
descriptor; the real ``CapabilityDescriptor`` is negotiated at handshake
|
||||
time via the transport's ``handshake()``. (Wiring the live transport +
|
||||
handshake into ``GatewayRunner`` is later-phase work; this task only proves
|
||||
the adapter is constructible through the registry behind the flag.)
|
||||
"""
|
||||
if not (force or relay_enabled()):
|
||||
return False
|
||||
|
||||
from gateway.platform_registry import PlatformEntry, platform_registry
|
||||
from gateway.relay.adapter import RelayAdapter
|
||||
from gateway.relay.descriptor import CONTRACT_VERSION, CapabilityDescriptor
|
||||
|
||||
def _factory(config):
|
||||
placeholder = CapabilityDescriptor(
|
||||
contract_version=CONTRACT_VERSION,
|
||||
platform="relay",
|
||||
label="Relay",
|
||||
max_message_length=4096,
|
||||
supports_draft_streaming=False,
|
||||
supports_edit=True,
|
||||
supports_threads=False,
|
||||
markdown_dialect="plain",
|
||||
len_unit="chars",
|
||||
)
|
||||
return RelayAdapter(config, placeholder)
|
||||
|
||||
platform_registry.register(
|
||||
PlatformEntry(
|
||||
name="relay",
|
||||
label="Relay",
|
||||
adapter_factory=_factory,
|
||||
check_fn=lambda: True,
|
||||
source="builtin",
|
||||
emoji="\U0001f50c",
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
|
|
|||
55
tests/gateway/relay/test_relay_registration.py
Normal file
55
tests/gateway/relay/test_relay_registration.py
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
"""RelayAdapter registration via the platform registry (relay Phase 1, Task 1.3).
|
||||
|
||||
Verifies the relay platform is registered ONLY behind the flag (dark-launch),
|
||||
constructed through the same registry path as plugin adapters.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from gateway.config import PlatformConfig
|
||||
from gateway.platform_registry import platform_registry
|
||||
from gateway.relay import register_relay_adapter, relay_enabled
|
||||
from gateway.relay.adapter import RelayAdapter
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _clean_registry(monkeypatch):
|
||||
"""Ensure each test starts/ends with no 'relay' entry and a clean env."""
|
||||
monkeypatch.delenv("HERMES_GATEWAY_RELAY", raising=False)
|
||||
platform_registry.unregister("relay")
|
||||
yield
|
||||
platform_registry.unregister("relay")
|
||||
|
||||
|
||||
def test_off_by_default():
|
||||
assert relay_enabled() is False
|
||||
assert register_relay_adapter() is False
|
||||
assert platform_registry.is_registered("relay") is False
|
||||
|
||||
|
||||
def test_enabled_by_env_flag(monkeypatch):
|
||||
monkeypatch.setenv("HERMES_GATEWAY_RELAY", "1")
|
||||
assert relay_enabled() is True
|
||||
assert register_relay_adapter() is True
|
||||
assert platform_registry.is_registered("relay") is True
|
||||
|
||||
|
||||
def test_force_registers_without_flag():
|
||||
assert register_relay_adapter(force=True) is True
|
||||
assert platform_registry.is_registered("relay") is True
|
||||
|
||||
|
||||
def test_create_adapter_yields_relay_adapter():
|
||||
register_relay_adapter(force=True)
|
||||
adapter = platform_registry.create_adapter("relay", PlatformConfig())
|
||||
assert isinstance(adapter, RelayAdapter)
|
||||
# Placeholder descriptor until handshake negotiates the real one.
|
||||
assert adapter.descriptor.platform == "relay"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("val,expected", [("0", False), ("", False), ("true", True), ("ON", True), ("yes", True)])
|
||||
def test_flag_parsing(monkeypatch, val, expected):
|
||||
monkeypatch.setenv("HERMES_GATEWAY_RELAY", val)
|
||||
assert relay_enabled() is expected
|
||||
Loading…
Add table
Add a link
Reference in a new issue