mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-21 15:55:43 +00:00
fix(gateway): harden multiplex primary token gate — canonical platform map + unserved-platform warning
Follow-ups to @SAMBAS123's #64986 salvage: - Replace the hardcoded token-platform set in _platform_has_bot_credential with PLATFORM_TOKEN_ENV_NAMES, a shared canonical map in gateway/config.py also used by the empty-token validation warning — one source of truth, so future token platforms can't silently bypass the gate or drift between the two sites. - After secondary-profile startup, warn loudly for any platform skipped on the primary that no secondary profile ended up serving: an enabled platform with no credential anywhere is a config error, not a silent no-op. - AUTHOR_MAP entry for the salvaged commit's author email.
This commit is contained in:
parent
86e7917ba7
commit
b4e4b5a43e
3 changed files with 42 additions and 18 deletions
|
|
@ -440,6 +440,22 @@ class ChannelOverride:
|
|||
)
|
||||
|
||||
|
||||
# Canonical map of platforms whose primary credential is ``PlatformConfig.token``
|
||||
# and the env var it loads from. Used for empty-token warnings at config
|
||||
# validation and by the multiplex primary-startup credential gate in
|
||||
# ``gateway.run`` (#64674). Platforms absent from this map authenticate some
|
||||
# other way (session files, port-bound webhooks, api_key-only) and must never
|
||||
# be skipped for a missing token.
|
||||
PLATFORM_TOKEN_ENV_NAMES: dict["Platform", str] = {
|
||||
Platform.TELEGRAM: "TELEGRAM_BOT_TOKEN",
|
||||
Platform.DISCORD: "DISCORD_BOT_TOKEN",
|
||||
Platform.SLACK: "SLACK_BOT_TOKEN",
|
||||
Platform.MATTERMOST: "MATTERMOST_TOKEN",
|
||||
Platform.MATRIX: "MATRIX_ACCESS_TOKEN",
|
||||
Platform.WEIXIN: "WEIXIN_TOKEN",
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class PlatformConfig:
|
||||
"""Configuration for a single messaging platform."""
|
||||
|
|
@ -1424,14 +1440,7 @@ def _validate_gateway_config(config: "GatewayConfig") -> None:
|
|||
|
||||
# Warn about empty bot tokens — platforms that loaded an empty string
|
||||
# won't connect and the cause can be confusing without a log line.
|
||||
_token_env_names = {
|
||||
Platform.TELEGRAM: "TELEGRAM_BOT_TOKEN",
|
||||
Platform.DISCORD: "DISCORD_BOT_TOKEN",
|
||||
Platform.SLACK: "SLACK_BOT_TOKEN",
|
||||
Platform.MATTERMOST: "MATTERMOST_TOKEN",
|
||||
Platform.MATRIX: "MATRIX_ACCESS_TOKEN",
|
||||
Platform.WEIXIN: "WEIXIN_TOKEN",
|
||||
}
|
||||
_token_env_names = PLATFORM_TOKEN_ENV_NAMES
|
||||
for platform, pconfig in config.platforms.items():
|
||||
if not pconfig.enabled:
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -1513,16 +1513,9 @@ def _platform_has_bot_credential(platform: "Platform", platform_config: "Platfor
|
|||
Platforms that do not use ``PlatformConfig.token`` always return True so we
|
||||
never skip them here (Signal session paths, port-binding HTTP adapters, etc.).
|
||||
"""
|
||||
# Keep in sync with gateway.config token env map used for empty-token warnings.
|
||||
token_platforms = {
|
||||
Platform.TELEGRAM,
|
||||
Platform.DISCORD,
|
||||
Platform.SLACK,
|
||||
Platform.MATTERMOST,
|
||||
Platform.MATRIX,
|
||||
Platform.WEIXIN,
|
||||
}
|
||||
if platform not in token_platforms:
|
||||
from gateway.config import PLATFORM_TOKEN_ENV_NAMES
|
||||
|
||||
if platform not in PLATFORM_TOKEN_ENV_NAMES:
|
||||
return True
|
||||
token = getattr(platform_config, "token", None) or ""
|
||||
if isinstance(token, str) and token.strip():
|
||||
|
|
@ -7232,6 +7225,7 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
|
|||
|
||||
# Initialize and connect each configured platform
|
||||
_multiplex_on = bool(getattr(self.config, "multiplex_profiles", False))
|
||||
_multiplex_skipped_platforms: list[Platform] = []
|
||||
for platform, platform_config in self.config.platforms.items():
|
||||
if await self._abort_startup_if_shutdown_requested():
|
||||
return True
|
||||
|
|
@ -7251,6 +7245,7 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
|
|||
"provide the token will still connect.",
|
||||
platform.value,
|
||||
)
|
||||
_multiplex_skipped_platforms.append(platform)
|
||||
continue
|
||||
enabled_platform_count += 1
|
||||
|
||||
|
|
@ -7396,6 +7391,25 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
|
|||
except Exception as e:
|
||||
logger.error("Secondary-profile adapter startup failed: %s", e, exc_info=True)
|
||||
|
||||
# A platform we skipped on the primary for a missing credential was
|
||||
# supposed to be picked up by a secondary profile that owns the token.
|
||||
# If none did, the platform is enabled in config.yaml yet silently
|
||||
# unserved — surface it loudly so the operator sees a config problem
|
||||
# instead of a quiet dead channel (#64674 follow-up).
|
||||
for _skipped in _multiplex_skipped_platforms:
|
||||
_served_by_secondary = any(
|
||||
_skipped in _profile_map
|
||||
for _profile_map in self._profile_adapters.values()
|
||||
)
|
||||
if not _served_by_secondary:
|
||||
logger.warning(
|
||||
"%s is enabled but no profile (default or secondary) "
|
||||
"provided a bot credential for it — the platform is not "
|
||||
"being served. Add its token to the profile that should "
|
||||
"own it, or disable the platform.",
|
||||
_skipped.value,
|
||||
)
|
||||
|
||||
if connected_count == 0:
|
||||
if startup_nonretryable_errors:
|
||||
reason = "; ".join(startup_nonretryable_errors)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ ACP_REGISTRY_MANIFEST = REPO_ROOT / "acp_registry" / "agent.json"
|
|||
|
||||
# Auto-extracted from noreply emails + manual overrides
|
||||
AUTHOR_MAP = {
|
||||
"doogie@spark.local": "SAMBAS123", # PR #64986 salvage (gateway: multiplex primary bot token scope)
|
||||
"41409874+2751738943@users.noreply.github.com": "2751738943", # PR #54785 salvage (tui: post-turn completion ownership routing)
|
||||
"Burgunthy@users.noreply.github.com": "Burgunthy", # PR #20096 salvage (gateway: profile-based routing for inbound messages)
|
||||
"75556242+webtecnica@users.noreply.github.com": "webtecnica", # PR #63360 salvage (nous: restore inference-api base_url)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue