simplify(compat): plugins/platforms+web — drop 7 re-exports + 3 aliases, repoint 1 caller + 11 tests, re-remove credential_summary

dingtalk: drop DINGTALK_TYPE_MAPPING/EXT_MAP re-exports. google_chat: card_spec_to_cards_v2 test -> .cards.
matrix: drop module-level MAX_MESSAGE_LENGTH alias (no importers). teams: drop TeamsSummaryWriter re-export
(teams_pipeline/runtime + tests -> summary_writer). wecom: drop WeComStreamExpiredError/STREAM_EXPIRED_ERRCODE/
MAX_INTERMEDIATE_FRAMES re-exports (tests -> .streaming). parallel: drop _get_parallel_client/_get_async_parallel_client
aliases (tests -> _get_sync_client). email: drop stale 'alias' comment (_esecret_int is the only name).
photon: re-remove credential_summary() (shim-only, cb9b7c36f3); its no-leak test now drives print_credential_summary.
This commit is contained in:
Teknium
2026-09-03 13:04:17 -07:00
parent ecf760db96
commit b610e603db
18 changed files with 60 additions and 106 deletions

View File

@@ -50,13 +50,7 @@ from gateway.config import Platform, PlatformConfig
from gateway.platforms.helpers import MessageDeduplicator, compile_mention_patterns
from gateway.platforms.base import BasePlatformAdapter, MessageEvent, SendResult
from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret
from plugins.platforms.dingtalk.inbound import ( # noqa: F401 — re-exported names
DINGTALK_TYPE_MAPPING,
EXT_MAP,
collect_download_codes,
extract_media,
extract_text,
)
from plugins.platforms.dingtalk.inbound import collect_download_codes, extract_media, extract_text
logger = logging.getLogger(__name__)

View File

@@ -54,7 +54,6 @@ _AUTH_METHOD_RE = re.compile(r"\b(dmarc|dkim|spf)\s*=\s*([a-z]+)", re.IGNORECASE
_AUTH_PROP_RE = re.compile(r"\b(header\.from|header\.d|smtp\.mailfrom|smtp\.from|envelope-from)\s*=\s*([^\s;]+)", re.IGNORECASE)
# Backwards-compatible alias for the name used by the original #59076 hunks.
def _esecret_int(name: str, default: int) -> int:
"""Scope-aware integer read."""
return coerce_port(str(_get_secret(name, "")).strip() or default, default)

View File

@@ -26,7 +26,7 @@ from urllib.parse import urlparse
from agent.secret_scope import is_multiplex_active
from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret
from .cards import card_spec_to_cards_v2, format_message as _format_message # noqa: F401 (re-exported)
from .cards import card_spec_to_cards_v2, format_message as _format_message
def _adc_would_borrow_foreign_credentials() -> bool:

View File

@@ -352,8 +352,6 @@ def _resolve_max_message_length(config) -> int:
return max(500, min(value, MATRIX_MAX_MESSAGE_LENGTH_CEILING))
MAX_MESSAGE_LENGTH = DEFAULT_MAX_MESSAGE_LENGTH # back-compat alias for importers of the module constant
# E2EE store dir is resolved per adapter in connect() (``_resolve_store_dir``), NOT at module scope:
# the multiplex gateway imports this once and a module constant would collide every profile's Olm
# identity in one crypto.db.

View File

@@ -713,36 +713,3 @@ def print_credential_summary(emit: Any = print) -> None:
" my number : " + (phone if phone else "✗ missing (run `hermes photon setup --phone ...`)"),
" assigned number : " + (assigned if assigned else "✗ missing (run `hermes photon setup`)")]
emit("\n".join(rows))
def credential_summary() -> Dict[str, str]:
"""Return a fully pre-formatted credential status dict (no raw secrets)."""
def _present_token() -> str:
return (
"✓ stored" if load_photon_token()
else "✗ missing (run `hermes photon setup`)"
)
def _present_project_id() -> str:
sid, _sec = load_project_credentials()
return sid or "✗ missing"
def _present_secret() -> str:
_sid, sec = load_project_credentials()
return "✓ stored" if sec else "✗ missing"
def _present_phone() -> str:
phone, _assigned = load_user_numbers()
return phone or "✗ missing (run `hermes photon setup --phone ...`)"
def _present_assigned_phone() -> str:
_phone, assigned = load_user_numbers()
return assigned or "✗ missing (run `hermes photon setup`)"
return {
"device_token": _present_token(),
"project_id": _present_project_id(),
"project_key": _present_secret(),
"phone_number": _present_phone(),
"assigned_phone_number": _present_assigned_phone(),
}

View File

@@ -58,7 +58,6 @@ from gateway.platforms.base import (
gateway_trust_env, BasePlatformAdapter, MessageEvent, MessageType, SendResult, cache_image_from_url, cache_media_bytes_async,
)
from gateway.platforms._shared import coerce_port, get_scoped_secret as _get_scoped_secret
from plugins.platforms.teams.summary_writer import TeamsSummaryWriter # noqa: F401 — re-exported for teams_pipeline
logger = logging.getLogger(__name__)
@@ -251,7 +250,7 @@ _SDK_IMPORTS = {
"microsoft_teams.cards": ("AdaptiveCard", "ExecuteAction", "TextBlock")}
# Keep the old name as an alias so existing test imports don't break. NOTE: ``check_requirements`` is the
# NOTE: ``check_requirements`` is the
# PASSIVE probe (registry ``check_fn``, status / unit tests) — it must never trigger a pip install.
# ``check_teams_requirements`` is the ACTIVE lazy-installer, registered as ``ensure_deps_fn``: the
# registry's ``create_adapter()`` runs it when the passive probe fails, right before the gateway connects

View File

@@ -34,9 +34,9 @@ from utils import env_float
from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret
from plugins.platforms.wecom.send_queue import ChatSendQueueMixin
from plugins.platforms.wecom.media import WeComMediaMixin, APP_CMD_SEND
from plugins.platforms.wecom.streaming import ( # noqa: F401 — re-exported for tests/stream_consumer
WeComStreamMixin, WeComStreamExpiredError, ReplyQueue, StreamTurn, APP_CMD_RESPONSE,
STREAM_EXPIRED_ERRCODE, STREAM_NOT_SUBSCRIBED_ERRCODE, MAX_STREAM_CONTENT_LENGTH, MAX_INTERMEDIATE_FRAMES,
from plugins.platforms.wecom.streaming import (
WeComStreamMixin, ReplyQueue, StreamTurn, APP_CMD_RESPONSE,
STREAM_NOT_SUBSCRIBED_ERRCODE, MAX_STREAM_CONTENT_LENGTH,
STREAM_SAFE_DURATION_SECONDS, STREAM_KEEPALIVE_INTERVAL_SECONDS, STREAM_KEEPALIVE_ENABLED_DEFAULT,
)

View File

@@ -53,7 +53,7 @@ def build_pipeline_runtime(gateway: Any) -> TeamsMeetingPipeline:
pipeline_config = build_pipeline_runtime_config(gateway.config)
if teams_config and teams_config.enabled and (pipeline_config.get("teams_delivery") or {}).get("enabled"):
try:
from plugins.platforms.teams.adapter import TeamsSummaryWriter
from plugins.platforms.teams.summary_writer import TeamsSummaryWriter
except ImportError:
logger.debug("TeamsSummaryWriter unavailable; Teams outbound delivery remains disabled until the adapter layer is present.")
else:

View File

@@ -37,10 +37,6 @@ def _get_async_client() -> Any:
return _client("_async_parallel_client", "AsyncParallel")
# Names re-exported by tools.web_tools for existing tests/callers.
_get_parallel_client, _get_async_parallel_client = _get_sync_client, _get_async_client
def _resolve_search_mode() -> str:
mode = os.getenv("PARALLEL_SEARCH_MODE", "agentic").lower().strip()
return mode if mode in {"fast", "one-shot", "agentic"} else "agentic"

View File

@@ -135,9 +135,9 @@ from plugins.platforms.google_chat.adapter import ( # noqa: E402
_is_google_owned_host,
_mime_for_message_type,
_redact_sensitive,
card_spec_to_cards_v2,
check_google_chat_requirements,
)
from plugins.platforms.google_chat.cards import card_spec_to_cards_v2 # noqa: E402
# ---------------------------------------------------------------------------
@@ -1735,7 +1735,7 @@ class TestCronSchedulerRegistry:
def test_google_chat_is_known_delivery_platform(self):
self._ensure_registered()
from cron.scheduler import _is_known_delivery_platform
from cron.scheduler_delivery import _is_known_delivery_platform
assert _is_known_delivery_platform("google_chat") is True

View File

@@ -191,7 +191,7 @@ if _mt and _teams_mod.TypingActivityInput is None:
_teams_mod.TypingActivityInput = _mt.TypingActivityInput
TeamsAdapter = _teams_mod.TeamsAdapter
TeamsSummaryWriter = _teams_mod.TeamsSummaryWriter
from plugins.platforms.teams.summary_writer import TeamsSummaryWriter # noqa: E402
check_requirements = _teams_mod.check_requirements
check_teams_requirements = _teams_mod.check_teams_requirements
validate_config = _teams_mod.validate_config

View File

@@ -162,7 +162,7 @@ class TestTeamsAdapterImportDoesNotLeakDotenv:
_install_fake_teams_sdk(monkeypatch)
_purge_teams_adapter_modules()
from plugins.platforms.teams.adapter import TeamsSummaryWriter
from plugins.platforms.teams.summary_writer import TeamsSummaryWriter
assert CANARY_KEY not in os.environ
assert TeamsSummaryWriter is not None

View File

@@ -920,7 +920,7 @@ class TestWeComNativeStreamingCapability:
assert WeComAdapter.MAX_STREAM_CONTENT_LENGTH == 20480
def test_stream_expired_errcode_constant(self):
from plugins.platforms.wecom.adapter import STREAM_EXPIRED_ERRCODE
from plugins.platforms.wecom.streaming import STREAM_EXPIRED_ERRCODE
assert STREAM_EXPIRED_ERRCODE == 846608
@@ -1078,7 +1078,8 @@ class TestSendStreamFrame:
@pytest.mark.asyncio
async def test_intermediate_frame_cap_drops_excess(self):
"""After MAX_INTERMEDIATE_FRAMES, further intermediate frames are dropped."""
from plugins.platforms.wecom.adapter import WeComAdapter, MAX_INTERMEDIATE_FRAMES
from plugins.platforms.wecom.adapter import WeComAdapter
from plugins.platforms.wecom.streaming import MAX_INTERMEDIATE_FRAMES
adapter = WeComAdapter(PlatformConfig(enabled=True))
adapter._last_chat_req_ids["chat-1"] = "req-1"
@@ -1179,9 +1180,8 @@ class TestSendStreamFrameFailures:
@pytest.mark.asyncio
async def test_846608_marks_chat_expired_and_returns_false(self):
"""846608 on finalize frame marks the chat expired and returns False."""
from plugins.platforms.wecom.adapter import (
STREAM_EXPIRED_ERRCODE, WeComAdapter,
)
from plugins.platforms.wecom.adapter import WeComAdapter
from plugins.platforms.wecom.streaming import STREAM_EXPIRED_ERRCODE
adapter = WeComAdapter(PlatformConfig(enabled=True))
adapter._last_chat_req_ids["chat-1"] = "req-1"
@@ -1392,7 +1392,8 @@ class TestSendClosesActiveStream:
@pytest.mark.asyncio
async def test_send_falls_through_when_stream_expired(self):
from plugins.platforms.wecom.adapter import STREAM_EXPIRED_ERRCODE, WeComAdapter
from plugins.platforms.wecom.adapter import WeComAdapter
from plugins.platforms.wecom.streaming import STREAM_EXPIRED_ERRCODE
adapter = WeComAdapter(PlatformConfig(enabled=True))
adapter._last_chat_req_ids["chat-1"] = "req-1"

View File

@@ -106,7 +106,8 @@ class TestPerTurnStreamIsolation:
@pytest.mark.asyncio
async def test_one_user_expired_others_unaffected(self):
"""User A hits stream expired; Users B and C continue normally."""
from plugins.platforms.wecom.adapter import STREAM_EXPIRED_ERRCODE, WeComAdapter
from plugins.platforms.wecom.adapter import WeComAdapter
from plugins.platforms.wecom.streaming import STREAM_EXPIRED_ERRCODE
adapter = WeComAdapter(PlatformConfig(enabled=True))
try:
@@ -155,7 +156,8 @@ class TestPerTurnStreamIsolation:
@pytest.mark.asyncio
async def test_one_turn_expired_other_continues(self):
"""When one turn hits stream expired, other concurrent turns can continue."""
from plugins.platforms.wecom.adapter import STREAM_EXPIRED_ERRCODE, WeComAdapter
from plugins.platforms.wecom.adapter import WeComAdapter
from plugins.platforms.wecom.streaming import STREAM_EXPIRED_ERRCODE
adapter = WeComAdapter(PlatformConfig(enabled=True))
try:

View File

@@ -33,11 +33,8 @@ from unittest.mock import AsyncMock
import pytest
from gateway.config import PlatformConfig
from plugins.platforms.wecom.adapter import (
WeComAdapter,
WeComStreamExpiredError,
STREAM_EXPIRED_ERRCODE,
)
from plugins.platforms.wecom.adapter import WeComAdapter
from plugins.platforms.wecom.streaming import STREAM_EXPIRED_ERRCODE, WeComStreamExpiredError
CHAT_ID = "chat-dup"

View File

@@ -340,16 +340,17 @@ def test_credential_summary_no_secret_leak(
project_secret="secret-bbbbbbbbbbb",
dashboard_project_id="dash-uuid",
)
summary = photon_auth.credential_summary()
blob = "\n".join(summary.values())
lines: list[str] = []
photon_auth.print_credential_summary(lines.append)
blob = "\n".join(lines)
assert "token-aaaa" not in blob
assert "secret-bbbb" not in blob
assert summary["device_token"].startswith("✓")
assert summary["project_key"].startswith("✓")
assert "device token : ✓" in blob
assert "project secret : ✓" in blob
# Unified id: dashboard id == Spectrum id, surfaced as one project id.
assert summary["project_id"] == "sp-uuid"
assert summary["phone_number"].startswith("✗ missing")
assert summary["assigned_phone_number"].startswith("✗ missing")
assert "project id : sp-uuid" in blob
assert "my number : ✗ missing" in blob
assert "assigned number : ✗ missing" in blob
# ---------------------------------------------------------------------------

View File

@@ -99,7 +99,7 @@ def test_build_pipeline_runtime_reuses_existing_teams_adapter_surface(monkeypatc
monkeypatch.setattr(runtime_module, "build_graph_client", lambda: object())
monkeypatch.setattr(runtime_module, "resolve_teams_pipeline_store_path", lambda: tmp_path / "teams-store.json")
monkeypatch.setattr("plugins.platforms.teams.adapter.TeamsSummaryWriter", FakeWriter)
monkeypatch.setattr("plugins.platforms.teams.summary_writer.TeamsSummaryWriter", FakeWriter)
gateway = SimpleNamespace(
config=GatewayConfig(

View File

@@ -4,7 +4,7 @@ Coverage:
_get_firecrawl_client() — configuration matrix, singleton caching,
constructor failure recovery, return value verification, edge cases.
_get_backend() — backend selection logic with env var combinations.
_get_parallel_client() — Parallel client configuration, singleton caching.
plugins.web.parallel.provider._get_sync_client() — Parallel client configuration, singleton caching.
check_web_api_key() — unified availability check across all web backends.
"""
@@ -35,10 +35,10 @@ class TestFirecrawlClientConfig:
):
os.environ.pop(key, None)
# Enable managed tools by default for these tests — patch both the
# local web_tools import and the managed_tool_gateway import so the
# tool_backend_helpers definition and the managed_tool_gateway import so the
# full firecrawl client init path sees True.
self._managed_patchers = [
patch("tools.web_tools.managed_nous_tools_enabled", return_value=True),
patch("tools.tool_backend_helpers.managed_nous_tools_enabled", return_value=True),
patch("tools.managed_tool_gateway.managed_nous_tools_enabled", return_value=True),
]
for p in self._managed_patchers:
@@ -65,18 +65,18 @@ class TestFirecrawlClientConfig:
def test_no_config_raises_with_helpful_message(self):
"""Neither key nor URL → ValueError with guidance."""
with patch("tools.web_tools.Firecrawl"):
with patch("tools.web_tools._read_nous_access_token", return_value=None):
from tools.web_tools import _get_firecrawl_client
with patch("plugins.web.firecrawl.provider.Firecrawl"):
with patch("tools.managed_tool_gateway.read_nous_access_token", return_value=None):
from plugins.web.firecrawl.provider import _get_firecrawl_client
with pytest.raises(ValueError, match="FIRECRAWL_API_KEY"):
_get_firecrawl_client()
def test_tool_gateway_domain_builds_firecrawl_gateway_origin(self):
"""Shared gateway domain should derive the Firecrawl vendor hostname."""
with patch.dict(os.environ, {"TOOL_GATEWAY_DOMAIN": "nousresearch.com"}):
with patch("tools.web_tools._read_nous_access_token", return_value="nous-token"):
with patch("tools.web_tools.Firecrawl") as mock_fc:
from tools.web_tools import _get_firecrawl_client
with patch("tools.managed_tool_gateway.read_nous_access_token", return_value="nous-token"):
with patch("plugins.web.firecrawl.provider.Firecrawl") as mock_fc:
from plugins.web.firecrawl.provider import _get_firecrawl_client
result = _get_firecrawl_client()
mock_fc.assert_called_once_with(
api_key="nous-token",
@@ -92,9 +92,9 @@ class TestFirecrawlClientConfig:
"""If Firecrawl() raises, next call should retry (not return None)."""
import tools.web_tools
with patch.dict(os.environ, {"FIRECRAWL_API_KEY": "fc-test"}):
with patch("tools.web_tools.Firecrawl") as mock_fc:
with patch("plugins.web.firecrawl.provider.Firecrawl") as mock_fc:
mock_fc.side_effect = [RuntimeError("init failed"), MagicMock()]
from tools.web_tools import _get_firecrawl_client
from plugins.web.firecrawl.provider import _get_firecrawl_client
with pytest.raises(RuntimeError):
_get_firecrawl_client()
@@ -109,9 +109,9 @@ class TestFirecrawlClientConfig:
def test_empty_string_key_no_url_raises(self):
"""FIRECRAWL_API_KEY='' with no URL → should raise."""
with patch.dict(os.environ, {"FIRECRAWL_API_KEY": ""}):
with patch("tools.web_tools.Firecrawl"):
with patch("tools.web_tools._read_nous_access_token", return_value=None):
from tools.web_tools import _get_firecrawl_client
with patch("plugins.web.firecrawl.provider.Firecrawl"):
with patch("tools.managed_tool_gateway.read_nous_access_token", return_value=None):
from plugins.web.firecrawl.provider import _get_firecrawl_client
with pytest.raises(ValueError):
_get_firecrawl_client()
@@ -120,9 +120,9 @@ class TestFirecrawlClientConfig:
from plugins.web.firecrawl import provider as firecrawl_provider
with patch("tools.web_tools._load_web_config", return_value={"backend": "firecrawl"}):
with patch("tools.web_tools._read_nous_access_token", return_value=None):
with patch("tools.web_tools.Firecrawl", side_effect=AssertionError("SDK path should not run")):
from tools.web_tools import _get_firecrawl_client
with patch("tools.managed_tool_gateway.read_nous_access_token", return_value=None):
with patch("plugins.web.firecrawl.provider.Firecrawl", side_effect=AssertionError("SDK path should not run")):
from plugins.web.firecrawl.provider import _get_firecrawl_client
result = _get_firecrawl_client()
@@ -217,7 +217,7 @@ class TestBackendSelection:
for key in self._ENV_KEYS:
os.environ.pop(key, None)
self._managed_patchers = [
patch("tools.web_tools.managed_nous_tools_enabled", return_value=True),
patch("tools.tool_backend_helpers.managed_nous_tools_enabled", return_value=True),
patch("tools.managed_tool_gateway.managed_nous_tools_enabled", return_value=True),
]
for p in self._managed_patchers:
@@ -412,7 +412,7 @@ class TestParallelClientConfig:
def test_creates_client_with_key(self):
"""PARALLEL_API_KEY set → creates Parallel client."""
with patch.dict(os.environ, {"PARALLEL_API_KEY": "test-key"}):
from tools.web_tools import _get_parallel_client
from plugins.web.parallel.provider import _get_sync_client as _get_parallel_client
from parallel import Parallel
client = _get_parallel_client()
assert client is not None
@@ -420,14 +420,14 @@ class TestParallelClientConfig:
def test_no_key_raises_with_helpful_message(self):
"""No PARALLEL_API_KEY → ValueError with guidance."""
from tools.web_tools import _get_parallel_client
from plugins.web.parallel.provider import _get_sync_client as _get_parallel_client
with pytest.raises(ValueError, match="PARALLEL_API_KEY"):
_get_parallel_client()
def test_singleton_returns_same_instance(self):
"""Second call returns cached client."""
with patch.dict(os.environ, {"PARALLEL_API_KEY": "test-key"}):
from tools.web_tools import _get_parallel_client
from plugins.web.parallel.provider import _get_sync_client as _get_parallel_client
client1 = _get_parallel_client()
client2 = _get_parallel_client()
assert client1 is client2
@@ -531,7 +531,7 @@ class TestCheckWebApiKey:
for key in self._ENV_KEYS:
os.environ.pop(key, None)
self._managed_patchers = [
patch("tools.web_tools.managed_nous_tools_enabled", return_value=True),
patch("tools.tool_backend_helpers.managed_nous_tools_enabled", return_value=True),
patch("tools.managed_tool_gateway.managed_nous_tools_enabled", return_value=True),
# ddgs availability is package-presence driven and the plugin
# registry can hold an available ddgs provider. Neutralize both
@@ -571,7 +571,7 @@ class TestCheckWebApiKey:
def test_configured_firecrawl_backend_accepts_managed_gateway(self):
with patch("tools.web_tools._load_web_config", return_value={"backend": "firecrawl"}):
with patch("tools.web_tools._peek_nous_access_token", return_value="nous-token"):
with patch("tools.managed_tool_gateway.peek_nous_access_token", return_value="nous-token"):
with patch.dict(os.environ, {"FIRECRAWL_GATEWAY_URL": "http://127.0.0.1:3002"}, clear=False):
from tools.web_tools import check_web_api_key
assert check_web_api_key() is True
@@ -709,7 +709,7 @@ class TestNonBuiltinProviderAvailability:
"""With only a custom provider registered (no built-in creds),
check_web_api_key() must return True."""
with patch("tools.web_tools._ddgs_package_importable", return_value=False), \
patch("tools.web_tools._peek_nous_access_token", return_value=None):
patch("tools.managed_tool_gateway.peek_nous_access_token", return_value=None):
from tools.web_tools import check_web_api_key
assert check_web_api_key() is True
@@ -717,7 +717,7 @@ class TestNonBuiltinProviderAvailability:
"""_get_backend() must return the custom provider name when it's
the only available provider."""
with patch("tools.web_tools._ddgs_package_importable", return_value=False), \
patch("tools.web_tools._peek_nous_access_token", return_value=None):
patch("tools.managed_tool_gateway.peek_nous_access_token", return_value=None):
from tools.web_tools import _get_backend
assert _get_backend() == "fake-plugin-prov"
@@ -726,7 +726,7 @@ class TestNonBuiltinProviderAvailability:
"""Per-capability selection (_get_extract_backend) must resolve the
custom provider when configured, instead of dead-ending — issue #32698."""
with patch("tools.web_tools._ddgs_package_importable", return_value=False), \
patch("tools.web_tools._peek_nous_access_token", return_value=None), \
patch("tools.managed_tool_gateway.peek_nous_access_token", return_value=None), \
patch("tools.web_tools._load_web_config",
return_value={"extract_backend": "fake-plugin-prov"}):
from tools.web_tools import _get_extract_backend
@@ -736,7 +736,7 @@ class TestNonBuiltinProviderAvailability:
"""web_search and web_extract tool entries must remain in the
registry when only a custom provider is available."""
with patch("tools.web_tools._ddgs_package_importable", return_value=False), \
patch("tools.web_tools._peek_nous_access_token", return_value=None):
patch("tools.managed_tool_gateway.peek_nous_access_token", return_value=None):
import tools.web_tools
web_search_entry = tools.web_tools.registry.get_entry("web_search")
web_extract_entry = tools.web_tools.registry.get_entry("web_extract")