fix: wire PII redaction + token empty warnings for plugin platforms

PII redaction: build_session_context_prompt() now checks the plugin
registry's pii_safe flag in addition to the hardcoded _PII_SAFE_PLATFORMS
frozenset. Plugin platforms that set pii_safe=True (e.g. phone-based
messaging bridges) get their user IDs redacted before LLM context.

Token empty warnings: the empty-token diagnostic at config load now
checks the plugin registry's required_env when a platform isn't in the
hardcoded _token_env_names dict. Catches 'enabled but empty' for
plugin platforms too.
This commit is contained in:
Teknium 2026-04-11 15:34:59 -07:00 committed by Teknium
parent 2e20f6ae2d
commit 457128d4e8
2 changed files with 32 additions and 13 deletions

View file

@ -891,6 +891,15 @@ def _validate_gateway_config(config: "GatewayConfig") -> None:
if not pconfig.enabled: if not pconfig.enabled:
continue continue
env_name = _token_env_names.get(platform) env_name = _token_env_names.get(platform)
if not env_name:
# Check plugin registry for required_env
try:
from gateway.platform_registry import platform_registry
entry = platform_registry.get(platform.value)
if entry and entry.required_env:
env_name = entry.required_env[0] # primary env var
except Exception:
pass
if env_name and pconfig.token is not None and not pconfig.token.strip(): if env_name and pconfig.token is not None and not pconfig.token.strip():
logger.warning( logger.warning(
"%s is enabled but %s is empty. " "%s is enabled but %s is empty. "

View file

@ -234,7 +234,7 @@ def build_session_context_prompt(
) -> str: ) -> str:
""" """
Build the dynamic system prompt section that tells the agent about its context. Build the dynamic system prompt section that tells the agent about its context.
This is injected into the system prompt so the agent knows: This is injected into the system prompt so the agent knows:
- Where messages are coming from - Where messages are coming from
- What platforms are connected - What platforms are connected
@ -246,13 +246,23 @@ def build_session_context_prompt(
Platforms like Discord are excluded because mentions need real IDs. Platforms like Discord are excluded because mentions need real IDs.
Routing still uses the original values (they stay in SessionSource). Routing still uses the original values (they stay in SessionSource).
""" """
# Only apply redaction on platforms where IDs aren't needed for mentions # Only apply redaction on platforms where IDs aren't needed for mentions.
redact_pii = redact_pii and context.source.platform in _PII_SAFE_PLATFORMS # Check both the hardcoded set (builtins) and the plugin registry.
_is_pii_safe = context.source.platform in _PII_SAFE_PLATFORMS
if not _is_pii_safe:
try:
from gateway.platform_registry import platform_registry
entry = platform_registry.get(context.source.platform.value)
if entry and entry.pii_safe:
_is_pii_safe = True
except Exception:
pass
redact_pii = redact_pii and _is_pii_safe
lines = [ lines = [
"## Current Session Context", "## Current Session Context",
"", "",
] ]
# Source info # Source info
platform_name = context.source.platform.value.title() platform_name = context.source.platform.value.title()
if context.source.platform == Platform.LOCAL: if context.source.platform == Platform.LOCAL:
@ -277,7 +287,7 @@ def build_session_context_prompt(
else: else:
desc = src.description desc = src.description
lines.append(f"**Source:** {platform_name} ({desc})") lines.append(f"**Source:** {platform_name} ({desc})")
# Channel topic (if available - provides context about the channel's purpose) # Channel topic (if available - provides context about the channel's purpose)
if context.source.chat_topic: if context.source.chat_topic:
lines.append(f"**Channel Topic:** {context.source.chat_topic}") lines.append(f"**Channel Topic:** {context.source.chat_topic}")
@ -302,7 +312,7 @@ def build_session_context_prompt(
if redact_pii: if redact_pii:
uid = _hash_sender_id(uid) uid = _hash_sender_id(uid)
lines.append(f"**User ID:** {uid}") lines.append(f"**User ID:** {uid}")
# Platform-specific behavioral notes # Platform-specific behavioral notes
if context.source.platform == Platform.SLACK: if context.source.platform == Platform.SLACK:
lines.append("") lines.append("")
@ -368,9 +378,9 @@ def build_session_context_prompt(
for p in context.connected_platforms: for p in context.connected_platforms:
if p != Platform.LOCAL: if p != Platform.LOCAL:
platforms_list.append(f"{p.value}: Connected ✓") platforms_list.append(f"{p.value}: Connected ✓")
lines.append(f"**Connected Platforms:** {', '.join(platforms_list)}") lines.append(f"**Connected Platforms:** {', '.join(platforms_list)}")
# Home channels # Home channels
if context.home_channels: if context.home_channels:
lines.append("") lines.append("")
@ -378,11 +388,11 @@ def build_session_context_prompt(
for platform, home in context.home_channels.items(): for platform, home in context.home_channels.items():
hc_id = _hash_chat_id(home.chat_id) if redact_pii else home.chat_id hc_id = _hash_chat_id(home.chat_id) if redact_pii else home.chat_id
lines.append(f" - {platform.value}: {home.name} (ID: {hc_id})") lines.append(f" - {platform.value}: {home.name} (ID: {hc_id})")
# Delivery options for scheduled tasks # Delivery options for scheduled tasks
lines.append("") lines.append("")
lines.append("**Delivery options for scheduled tasks:**") lines.append("**Delivery options for scheduled tasks:**")
from hermes_constants import display_hermes_home from hermes_constants import display_hermes_home
# Origin delivery # Origin delivery
@ -398,15 +408,15 @@ def build_session_context_prompt(
lines.append( lines.append(
f"- `\"local\"` → Save to local files only ({display_hermes_home()}/cron/output/)" f"- `\"local\"` → Save to local files only ({display_hermes_home()}/cron/output/)"
) )
# Platform home channels # Platform home channels
for platform, home in context.home_channels.items(): for platform, home in context.home_channels.items():
lines.append(f"- `\"{platform.value}\"` → Home channel ({home.name})") lines.append(f"- `\"{platform.value}\"` → Home channel ({home.name})")
# Note about explicit targeting # Note about explicit targeting
lines.append("") lines.append("")
lines.append("*For explicit targeting, use `\"platform:chat_id\"` format if the user provides a specific chat ID.*") lines.append("*For explicit targeting, use `\"platform:chat_id\"` format if the user provides a specific chat ID.*")
return "\n".join(lines) return "\n".join(lines)