diff --git a/COMPAT_MANIFEST.md b/COMPAT_MANIFEST.md index 0c7b80df42..4589374cc4 100644 --- a/COMPAT_MANIFEST.md +++ b/COMPAT_MANIFEST.md @@ -1025,7 +1025,7 @@ to the public equivalent or the new module. Test monkeypatch seams are likewise |---|---|---| | `Any` | import | `typing` | | `HISTORY_UNREADABLE` | moved-lazy | `gateway.slash_commands_status` | -| `MessageType` | moved-lazy | `gateway.platforms.base` | +| `MessageType` | moved-lazy | `gateway.platforms.event` | | `SessionSource` | moved-lazy | `gateway.session` | | `base_url_host_matches` | moved-lazy | `utils` | | `build_session_key` | moved-lazy | `gateway.session` | @@ -2547,7 +2547,7 @@ to the public equivalent or the new module. Test monkeypatch seams are likewise |---|---|---| | `DINGTALK_TYPE_MAPPING` | moved-lazy | `plugins.platforms.dingtalk.inbound` | | `EXT_MAP` | restored-def | `(deleted; BASE body restored)` | -| `MessageType` | moved-lazy | `gateway.platforms.base` | +| `MessageType` | moved-lazy | `gateway.platforms.event` | ### `plugins.platforms.discord.adapter` @@ -2602,7 +2602,7 @@ to the public equivalent or the new module. Test monkeypatch seams are likewise | name | kind | new location | |---|---|---| -| `ProcessingOutcome` | moved-lazy | `gateway.platforms.base` | +| `ProcessingOutcome` | moved-lazy | `gateway.platforms.event` | | `resolve_sidecar_dir` | moved-lazy | `plugins.platforms.photon.sidecar_paths` | ### `plugins.platforms.photon.auth` diff --git a/compat_manifest.json b/compat_manifest.json index e663cd0ff6..9c3a37ca0c 100644 --- a/compat_manifest.json +++ b/compat_manifest.json @@ -2646,7 +2646,7 @@ "facade": "gateway.slash_commands", "name": "MessageType", "kind": "moved-lazy", - "target": "gateway.platforms.base" + "target": "gateway.platforms.event" }, { "facade": "gateway.slash_commands", @@ -8262,7 +8262,7 @@ "facade": "plugins.platforms.dingtalk.adapter", "name": "MessageType", "kind": "moved-lazy", - "target": "gateway.platforms.base" + "target": "gateway.platforms.event" }, { "facade": "plugins.platforms.discord.adapter", @@ -8340,7 +8340,7 @@ "facade": "plugins.platforms.photon.adapter", "name": "ProcessingOutcome", "kind": "moved-lazy", - "target": "gateway.platforms.base" + "target": "gateway.platforms.event" }, { "facade": "plugins.platforms.photon.adapter", diff --git a/gateway/platforms/ADDING_A_PLATFORM.md b/gateway/platforms/ADDING_A_PLATFORM.md index b23b7b8c8c..c8e3f67e3c 100644 --- a/gateway/platforms/ADDING_A_PLATFORM.md +++ b/gateway/platforms/ADDING_A_PLATFORM.md @@ -135,7 +135,7 @@ def check__requirements() -> bool: - Use `self.build_source(...)` to construct `SessionSource` objects - Call `self.handle_message(event)` to dispatch inbound messages to the gateway -- Use `MessageEvent`, `MessageType`, `SendResult` from base +- Use `MessageEvent`, `MessageType` from `gateway.platforms.event` and `SendResult` from base - Use `cache_image_from_bytes`, `cache_audio_from_bytes`, `cache_document_from_bytes` for attachments - Filter self-messages (prevent reply loops) - Filter sync/echo messages if the platform has them diff --git a/gateway/platforms/__init__.py b/gateway/platforms/__init__.py index c756e2be96..2cf615e3ea 100644 --- a/gateway/platforms/__init__.py +++ b/gateway/platforms/__init__.py @@ -1,5 +1,6 @@ """Platform adapters for messaging integrations (receive, send, auth, media).""" -from .base import BasePlatformAdapter, MessageEvent, SendResult +from .base import BasePlatformAdapter, SendResult +from .event import MessageEvent __all__ = ["BasePlatformAdapter", "MessageEvent", "SendResult"] diff --git a/gateway/platforms/base.py b/gateway/platforms/base.py index 6fc79fcc84..37972956be 100644 --- a/gateway/platforms/base.py +++ b/gateway/platforms/base.py @@ -423,15 +423,14 @@ def is_host_excluded_by_no_proxy(hostname: str, no_proxy_value: str | None = Non import dataclasses from dataclasses import dataclass, field -from datetime import datetime from pathlib import Path from typing import TYPE_CHECKING, Dict, List, Optional, Any, Callable, Awaitable, Tuple, Union -from enum import Enum sys.path.insert(0, str(Path(__file__).resolve().parents[2])) from gateway.config import Platform, PlatformConfig from gateway.platforms.helpers import fence_state_after +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from gateway.session import SessionSource, build_session_key from gateway.session_transcript import TranscriptReadError from hermes_constants import get_default_hermes_root, get_hermes_dir, get_hermes_home @@ -1505,91 +1504,6 @@ async def cache_media_bytes_async( ) -class MessageType(Enum): - """Types of incoming messages.""" - TEXT = "text" - LOCATION = "location" - PHOTO = "photo" - VIDEO = "video" - AUDIO = "audio" - VOICE = "voice" - DOCUMENT = "document" - STICKER = "sticker" - COMMAND = "command" # /command style - - -class ProcessingOutcome(Enum): - """Result classification for message-processing lifecycle hooks.""" - SUCCESS = "success" - FAILURE = "failure" - CANCELLED = "cancelled" - - -@dataclass -class MessageEvent: - """Incoming message from a platform — the normalized shape all adapters produce.""" - text: str - message_type: MessageType = MessageType.TEXT - # Author, mirrored from ``source`` for per-message prompt builders; None for non-IM sources. - user_id: Optional[str] = None - user_name: Optional[str] = None - source: SessionSource = None - raw_message: Any = None - message_id: Optional[str] = None - # Platform update id (Telegram ``update_id``): ``/restart`` records it so the new gateway - # advances past it even if PTB's shutdown ACK times out. - platform_update_id: Optional[int] = None - # Media attachments: local file paths (for vision tool access) - media_urls: List[str] = field(default_factory=list) - media_types: List[str] = field(default_factory=list) - # Per-attachment text-inlining contract; None = legacy "text/* already inlined into ``text``". - media_text_inlined: List[Optional[bool]] = field(default_factory=list) - reply_to_message_id: Optional[str] = None - reply_to_text: Optional[str] = None # Text of the replied-to message (for context injection) - reply_to_author_id: Optional[str] = None - reply_to_author_name: Optional[str] = None - reply_to_is_own_message: bool = False # True when the user replied to this bot/assistant's message - # Structured interactive-prompt reply (relay only): {prompt_id, option_id, label?, - # prompt_message_id?}; routed to the approval/slash-confirm/clarify resolvers BEFORE dispatch. - prompt_response: Optional[Dict[str, Any]] = None - # Auto-loaded skill(s) for topic/channel bindings; a single name or ordered list. - auto_skill: Optional[str | list[str]] = None - # Per-channel ephemeral system prompt; applied at API call time, never persisted to transcript. - channel_prompt: Optional[str] = None - # History-backfilled channel context (missed under require_mention); kept out of ``text`` so - # run.py's sender-prefix logic sees only the trigger message. - channel_context: Optional[str] = None - # Set for synthetic events (e.g. background-process notifications) that must bypass user authorization. - internal: bool = False - # Free-form per-event metadata (e.g. ``whatsapp_from_owner=True``); plugins must ``.get()``. - metadata: Dict[str, Any] = field(default_factory=dict) - timestamp: datetime = field(default_factory=datetime.now) - # May this event resolve gateway commands / control prompts? Proactive plugin events set False - # so untrusted payload text stays conversational. Kept last for positional compat. - allow_gateway_control: bool = True - - def is_command(self) -> bool: - """Check if this is a command message (e.g., /new, /reset).""" - return self.allow_gateway_control and (self.text or "").lstrip().startswith("/") - - def get_command(self) -> Optional[str]: - """Extract command name if this is a command message.""" - if not self.is_command(): - return None - raw = (self.text or "").lstrip().split(maxsplit=1)[0][1:].lower().split("@", 1)[0] - # Reject file paths: valid command names never contain / - return None if "/" in raw else raw - - def get_command_args(self) -> str: - """Get the arguments after a command.""" - if not self.is_command(): - return self.text - parts = (self.text or "").lstrip().split(maxsplit=1) - args = parts[1] if len(parts) > 1 else "" - # iOS auto-corrects -- to — (em dash) and - to – (en dash) - return args.replace("\u2014\u2014", "--").replace("\u2014", "--").replace("\u2013", "-") - - @dataclass class TextDebounceState: event: MessageEvent diff --git a/gateway/platforms/bluebubbles.py b/gateway/platforms/bluebubbles.py index 8c0eb2788c..47b83e1bf9 100644 --- a/gateway/platforms/bluebubbles.py +++ b/gateway/platforms/bluebubbles.py @@ -19,8 +19,10 @@ import httpx from gateway.config import Platform, PlatformConfig from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, SendResult, - cache_image_from_bytes_async, cache_audio_from_bytes_async, cache_document_from_bytes_async) + BasePlatformAdapter, SendResult, + cache_image_from_bytes_async, cache_audio_from_bytes_async, cache_document_from_bytes_async, +) +from gateway.platforms.event import MessageEvent, MessageType from .media_cache import ext_for_mime from gateway.platforms.helpers import compile_mention_patterns, strip_markdown from utils import TRUTHY_STRINGS diff --git a/gateway/platforms/event.py b/gateway/platforms/event.py new file mode 100644 index 0000000000..0de062922b --- /dev/null +++ b/gateway/platforms/event.py @@ -0,0 +1,99 @@ +"""Inbound message event types shared by every gateway platform adapter. + +A leaf module: adapters, helpers and the runner import it, so it must not import from +gateway.platforms.*. +""" + +from dataclasses import dataclass, field +from datetime import datetime +from enum import Enum +from typing import Any, Dict, List, Optional + +from gateway.session import SessionSource + + +class MessageType(Enum): + """Types of incoming messages.""" + TEXT = "text" + LOCATION = "location" + PHOTO = "photo" + VIDEO = "video" + AUDIO = "audio" + VOICE = "voice" + DOCUMENT = "document" + STICKER = "sticker" + COMMAND = "command" # /command style + + +class ProcessingOutcome(Enum): + """Result classification for message-processing lifecycle hooks.""" + SUCCESS = "success" + FAILURE = "failure" + CANCELLED = "cancelled" + + +@dataclass +class MessageEvent: + """Incoming message from a platform — the normalized shape all adapters produce.""" + text: str + message_type: MessageType = MessageType.TEXT + # Author, mirrored from ``source`` for per-message prompt builders; None for non-IM sources. + user_id: Optional[str] = None + user_name: Optional[str] = None + # None only in isolated unit tests; production always sets it. Typing it Optional + # exposes ~60 unguarded ``.source.`` reads, so that is a separate change. + source: SessionSource = None + raw_message: Any = None + message_id: Optional[str] = None + # Platform update id (Telegram ``update_id``): ``/restart`` records it so the new gateway + # advances past it even if PTB's shutdown ACK times out. + platform_update_id: Optional[int] = None + # Media attachments: local file paths (for vision tool access) + media_urls: List[str] = field(default_factory=list) + media_types: List[str] = field(default_factory=list) + # Per-attachment text-inlining contract; None = legacy "text/* already inlined into ``text``". + media_text_inlined: List[Optional[bool]] = field(default_factory=list) + reply_to_message_id: Optional[str] = None + reply_to_text: Optional[str] = None # Text of the replied-to message (for context injection) + reply_to_author_id: Optional[str] = None + reply_to_author_name: Optional[str] = None + reply_to_is_own_message: bool = False # True when the user replied to this bot/assistant's message + # Structured interactive-prompt reply (relay only): {prompt_id, option_id, label?, + # prompt_message_id?}; routed to the approval/slash-confirm/clarify resolvers BEFORE dispatch. + prompt_response: Optional[Dict[str, Any]] = None + # Auto-loaded skill(s) for topic/channel bindings; a single name or ordered list. + auto_skill: Optional[str | list[str]] = None + # Per-channel ephemeral system prompt; applied at API call time, never persisted to transcript. + channel_prompt: Optional[str] = None + # History-backfilled channel context (missed under require_mention); kept out of ``text`` so + # run.py's sender-prefix logic sees only the trigger message. + channel_context: Optional[str] = None + # Set for synthetic events (e.g. background-process notifications) that must bypass user authorization. + internal: bool = False + # Free-form per-event metadata (e.g. ``whatsapp_from_owner=True``); plugins must ``.get()``. + metadata: Dict[str, Any] = field(default_factory=dict) + timestamp: datetime = field(default_factory=datetime.now) + # May this event resolve gateway commands / control prompts? Proactive plugin events set False + # so untrusted payload text stays conversational. Kept last for positional compat. + allow_gateway_control: bool = True + + def is_command(self) -> bool: + """Check if this is a command message (e.g., /new, /reset).""" + return self.allow_gateway_control and (self.text or "").lstrip().startswith("/") + + def get_command(self) -> Optional[str]: + """Extract command name if this is a command message.""" + if not self.is_command(): + return None + raw = (self.text or "").lstrip().split(maxsplit=1)[0][1:].lower().split("@", 1)[0] + # Reject file paths: valid command names never contain / + return None if "/" in raw else raw + + def get_command_args(self) -> str: + """Get the arguments after a command.""" + if not self.is_command(): + return self.text + parts = (self.text or "").lstrip().split(maxsplit=1) + args = parts[1] if len(parts) > 1 else "" + # iOS auto-corrects -- to — (em dash) and - to – (en dash) + return args.replace("\u2014\u2014", "--").replace("\u2014", "--").replace("\u2013", "-") diff --git a/gateway/platforms/helpers.py b/gateway/platforms/helpers.py index ae0cb72555..db2e4694c9 100644 --- a/gateway/platforms/helpers.py +++ b/gateway/platforms/helpers.py @@ -9,8 +9,7 @@ import logging import re import time from pathlib import Path -from typing import Any, Protocol - +from gateway.platforms.event import MessageEvent from utils import atomic_json_write logger = logging.getLogger(__name__) @@ -525,14 +524,6 @@ from typing import TYPE_CHECKING # noqa: F401,E402 import asyncio # noqa: F401,E402 import asyncio # noqa: F401,E402 -class BatchableEvent(Protocol): - """What TextBatchAggregator needs from an inbound event. gateway.platforms.base.MessageEvent - satisfies it; base imports this module at import time, so the concrete class cannot be named here.""" - - text: str - source: Any - - class TextBatchAggregator: """Aggregates rapid-fire text events into single messages. @@ -565,14 +556,14 @@ class TextBatchAggregator: self._batch_delay = batch_delay self._split_delay = split_delay self._split_threshold = split_threshold - self._pending: Dict[str, BatchableEvent] = {} + self._pending: Dict[str, MessageEvent] = {} self._pending_tasks: Dict[str, asyncio.Task] = {} def is_enabled(self) -> bool: """Return True if batching is active (delay > 0).""" return self._batch_delay > 0 - def enqueue(self, event: BatchableEvent, key: str) -> None: + def enqueue(self, event: MessageEvent, key: str) -> None: """Add *event* to the pending batch for *key*.""" chunk_len = len(event.text or "") existing = self._pending.get(key) diff --git a/gateway/platforms/msgraph_webhook.py b/gateway/platforms/msgraph_webhook.py index 3e59f76793..326aed18c6 100644 --- a/gateway/platforms/msgraph_webhook.py +++ b/gateway/platforms/msgraph_webhook.py @@ -22,7 +22,9 @@ except ImportError: from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, SendResult, is_network_accessible) + BasePlatformAdapter, SendResult, is_network_accessible, +) +from gateway.platforms.event import MessageEvent, MessageType logger = logging.getLogger(__name__) diff --git a/gateway/platforms/qqbot/adapter.py b/gateway/platforms/qqbot/adapter.py index 87f4c04857..c4f6caf6dd 100644 --- a/gateway/platforms/qqbot/adapter.py +++ b/gateway/platforms/qqbot/adapter.py @@ -39,8 +39,10 @@ except ImportError: from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( - gateway_trust_env, BasePlatformAdapter, MessageEvent, MessageType, SendResult, - _ssrf_redirect_guard, cache_document_from_bytes_async, cache_image_from_bytes_async) + gateway_trust_env, BasePlatformAdapter, SendResult, + _ssrf_redirect_guard, cache_document_from_bytes_async, cache_image_from_bytes_async, +) +from gateway.platforms.event import MessageEvent, MessageType from gateway.platforms.helpers import strip_markdown from gateway.platforms.media_cache import ext_for_mime diff --git a/gateway/platforms/signal.py b/gateway/platforms/signal.py index f73c39045e..9c2f8c91d1 100644 --- a/gateway/platforms/signal.py +++ b/gateway/platforms/signal.py @@ -25,8 +25,10 @@ import httpx from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, ProcessingOutcome, SendResult, cache_image_from_bytes_async, - cache_audio_from_bytes_async, cache_document_from_bytes_async, cache_image_from_url, utf16_len) + BasePlatformAdapter, SendResult, cache_image_from_bytes_async, + cache_audio_from_bytes_async, cache_document_from_bytes_async, cache_image_from_url, utf16_len, +) +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from gateway.platforms.helpers import redact_phone from gateway.platforms.media_cache import mime_for_ext from tools.audio_container import CONTAINER_TO_EXT, sniff_container diff --git a/gateway/platforms/webhook.py b/gateway/platforms/webhook.py index 1e7ca78b1c..69317f90bd 100644 --- a/gateway/platforms/webhook.py +++ b/gateway/platforms/webhook.py @@ -30,7 +30,8 @@ except ImportError: web = None # type: ignore[assignment] from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.platforms.webhook_filters import DEFAULT_SCRIPT_TIMEOUT_SECONDS, WebhookRouteProcessor from gateway.response_filters import is_autonomous_silence_response diff --git a/gateway/platforms/weixin.py b/gateway/platforms/weixin.py index 2f4e97f53a..c2fc011e87 100644 --- a/gateway/platforms/weixin.py +++ b/gateway/platforms/weixin.py @@ -30,9 +30,10 @@ CRYPTO_AVAILABLE = Cipher is not None from gateway.config import Platform, PlatformConfig from gateway.platforms.helpers import MessageDeduplicator, greedy_pack_blocks from gateway.platforms.base import ( - _IMAGE_EXTS, _VIDEO_EXTS, gateway_trust_env, BasePlatformAdapter, MessageEvent, MessageType, SendResult, + _IMAGE_EXTS, _VIDEO_EXTS, gateway_trust_env, BasePlatformAdapter, SendResult, cache_audio_from_bytes_async, cache_document_from_bytes_async, cache_image_from_bytes_async, ) +from gateway.platforms.event import MessageEvent, MessageType from hermes_constants import get_hermes_home from utils import atomic_json_write from agent.secret_scope import UnscopedSecretError, get_secret diff --git a/gateway/platforms/whatsapp_cloud.py b/gateway/platforms/whatsapp_cloud.py index f8ca5fea4d..8daf427cb5 100644 --- a/gateway/platforms/whatsapp_cloud.py +++ b/gateway/platforms/whatsapp_cloud.py @@ -39,7 +39,8 @@ except ImportError: httpx = None # type: ignore[assignment] from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.platforms.whatsapp_common import _OPTIN_TRUTHY, WhatsAppBehaviorMixin, _get_wsecret from gateway.platforms.media_cache import ext_for_mime from gateway import rich_sent_store diff --git a/gateway/platforms/yuanbao.py b/gateway/platforms/yuanbao.py index dc49137580..d2a8d04536 100644 --- a/gateway/platforms/yuanbao.py +++ b/gateway/platforms/yuanbao.py @@ -43,9 +43,10 @@ except ImportError: from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, SendResult, + BasePlatformAdapter, SendResult, cache_document_from_bytes_async, cache_image_from_bytes_async, cache_video_from_bytes_async, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.platforms import helpers as _mdchunk from gateway.platforms._shared import get_scoped_secret as _yb_secret from gateway.platforms.helpers import MessageDeduplicator diff --git a/gateway/relay/adapter.py b/gateway/relay/adapter.py index 2e65a7c4a3..987a81a195 100644 --- a/gateway/relay/adapter.py +++ b/gateway/relay/adapter.py @@ -22,8 +22,9 @@ from typing import Any, Callable, Dict, Optional, Tuple, Union from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, ProcessingOutcome, SendResult, + BasePlatformAdapter, SendResult, ) +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from gateway.relay.descriptor import CapabilityDescriptor from gateway.relay.media import RelayMediaClient from gateway.relay.transport import RelayTransport diff --git a/gateway/relay/transport.py b/gateway/relay/transport.py index b075f2393d..fb4fcb600a 100644 --- a/gateway/relay/transport.py +++ b/gateway/relay/transport.py @@ -11,7 +11,7 @@ from __future__ import annotations from typing import Any, Awaitable, Callable, Dict, Optional, Protocol, runtime_checkable -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.relay.descriptor import CapabilityDescriptor # Callback the transport invokes for each inbound normalized event. diff --git a/gateway/relay/ws_transport.py b/gateway/relay/ws_transport.py index 55daa52e52..ac8244bf94 100644 --- a/gateway/relay/ws_transport.py +++ b/gateway/relay/ws_transport.py @@ -20,7 +20,7 @@ import uuid from dataclasses import dataclass from typing import Any, Awaitable, Callable, Dict, List, Optional -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource from gateway.relay.descriptor import CapabilityDescriptor from gateway.relay.transport import InboundHandler diff --git a/gateway/run.py b/gateway/run.py index 0e2faabbd0..f0f84bbbf5 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -38,8 +38,8 @@ from agent.conversation_compression import ( from agent.conversation_loop import INTERRUPT_WAITING_FOR_MODEL_PREFIX from agent.interrupt_compat import request_hard_interrupt from agent.turn_context import compression_made_progress -from hermes_cli.config import _is_ssh_remote_tilde_cwd, cfg_get from agent.session_activity import ActivityProvenance +from hermes_cli.config import _is_ssh_remote_tilde_cwd, cfg_get from hermes_cli.fallback_config import get_fallback_chain # Per-session AIAgent cache bounds (agents are heavy); see _enforce_agent_cache_cap/_session_housekeeping_watcher. @@ -2063,10 +2063,9 @@ from gateway.run_goals import GatewayGoalsMixin from gateway.run_agent_cache import GatewayAgentCacheMixin from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, _reply_anchor_for_event, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.restart import ( DEFAULT_GATEWAY_CRON_DRAIN_TIMEOUT, DEFAULT_GATEWAY_RESTART_AFTER_TURN_TIMEOUT, diff --git a/gateway/run_busy.py b/gateway/run_busy.py index 19c850ca9a..3f5630d46b 100644 --- a/gateway/run_busy.py +++ b/gateway/run_busy.py @@ -17,7 +17,8 @@ import time from agent.i18n import t from agent.session_activity import format_iteration_progress from gateway.config import Platform -from gateway.platforms.base import EphemeralReply, MessageEvent, MessageType +from gateway.platforms.base import EphemeralReply +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource from typing import Any, Dict, Optional, Union diff --git a/gateway/run_goals.py b/gateway/run_goals.py index cc57d80bf2..b3f6e80c87 100644 --- a/gateway/run_goals.py +++ b/gateway/run_goals.py @@ -13,7 +13,7 @@ import time from contextlib import suppress from typing import TYPE_CHECKING, Any -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType if TYPE_CHECKING: # string annotations only; never imported at runtime (cycle) from gateway.run import GatewayRunner # noqa: F401 diff --git a/gateway/run_inbound.py b/gateway/run_inbound.py index 77e9c2bf28..94a9c8346d 100644 --- a/gateway/run_inbound.py +++ b/gateway/run_inbound.py @@ -18,7 +18,8 @@ import re import time from contextlib import suppress from gateway.config import Platform -from gateway.platforms.base import EphemeralReply, MessageEvent, MessageType +from gateway.platforms.base import EphemeralReply +from gateway.platforms.event import MessageEvent, MessageType from gateway.run_common import _UNSET from gateway.session import ( SessionSource, is_shared_multi_user_session, neutralize_untrusted_inline_text diff --git a/gateway/run_notifications.py b/gateway/run_notifications.py index 194dcd4718..7199a8d785 100644 --- a/gateway/run_notifications.py +++ b/gateway/run_notifications.py @@ -17,7 +17,7 @@ from pathlib import Path from typing import Any, Dict, Optional, cast from gateway.config import Platform, _BUILTIN_PLATFORM_VALUES -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionEntry, SessionSource from gateway.run_shutdown import _log_suppressed, _notice_target_key, _send_error, _send_failed diff --git a/gateway/run_startup.py b/gateway/run_startup.py index 72fe624024..818c2c3f6b 100644 --- a/gateway/run_startup.py +++ b/gateway/run_startup.py @@ -18,7 +18,8 @@ from contextlib import suppress from datetime import datetime from gateway.config import Platform from gateway.delivery import looks_like_telegram_private_chat_id -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType +from gateway.platforms.base import BasePlatformAdapter +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key from gateway.restart import ( DEFAULT_GATEWAY_CRON_DRAIN_TIMEOUT, GATEWAY_FATAL_CONFIG_EXIT_CODE, is_global_startup_conflict diff --git a/gateway/run_topics.py b/gateway/run_topics.py index 54777a9ff0..e1445f7b40 100644 --- a/gateway/run_topics.py +++ b/gateway/run_topics.py @@ -16,7 +16,8 @@ from typing import TYPE_CHECKING, Optional, Tuple from agent.compaction_display import project_compaction_message_for_display from agent.i18n import t from gateway.config import Platform -from gateway.platforms.base import MessageEvent, _prefix_within_utf16_limit, utf16_len +from gateway.platforms.base import _prefix_within_utf16_limit, utf16_len +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource from utils import is_truthy_value diff --git a/gateway/run_turn.py b/gateway/run_turn.py index 2e04bea8a9..3a861ba632 100644 --- a/gateway/run_turn.py +++ b/gateway/run_turn.py @@ -21,7 +21,8 @@ from contextlib import nullcontext, suppress from contextvars import copy_context from gateway.config import Platform from gateway.media_repair import repair_explicit_computer_use_media_paths -from gateway.platforms.base import BasePlatformAdapter, MessageEvent +from gateway.platforms.base import BasePlatformAdapter +from gateway.platforms.event import MessageEvent from gateway.session import ( SessionSource, _session_key_namespace, build_channel_continuity_note, build_session_context, diff --git a/gateway/run_voice.py b/gateway/run_voice.py index 6d40cc813a..d042733dad 100644 --- a/gateway/run_voice.py +++ b/gateway/run_voice.py @@ -18,7 +18,8 @@ from types import SimpleNamespace from typing import Dict, List, Optional from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType, build_auto_tts_output_path +from gateway.platforms.base import build_auto_tts_output_path +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource logger = logging.getLogger("gateway.run") # log-record parity with the origin module diff --git a/gateway/slash_commands.py b/gateway/slash_commands.py index 4673315d07..c48d87e25c 100644 --- a/gateway/slash_commands.py +++ b/gateway/slash_commands.py @@ -21,7 +21,8 @@ from typing import Optional, Union from agent.i18n import t from gateway.config import HomeChannel, Platform, PlatformConfig, persist_home_channel -from gateway.platforms.base import EphemeralReply, MessageEvent +from gateway.platforms.base import EphemeralReply +from gateway.platforms.event import MessageEvent from gateway.session import AsyncSessionStore from gateway.session_transcript import TranscriptReadError from gateway.slash_commands_goals import GatewayGoalCommandsMixin @@ -1252,7 +1253,7 @@ import hashlib # noqa: F401,E402 _PLUGIN_COMPAT_LAZY = { 'HISTORY_UNREADABLE': ('gateway.slash_commands_status', 'HISTORY_UNREADABLE'), - 'MessageType': ('gateway.platforms.base', 'MessageType'), + 'MessageType': ('gateway.platforms.event', 'MessageType'), 'SessionSource': ('gateway.session', 'SessionSource'), 'base_url_host_matches': ('utils', 'base_url_host_matches'), 'build_session_key': ('gateway.session', 'build_session_key'), diff --git a/gateway/slash_commands_goals.py b/gateway/slash_commands_goals.py index 615680e5c5..8b74e7a4cb 100644 --- a/gateway/slash_commands_goals.py +++ b/gateway/slash_commands_goals.py @@ -6,7 +6,7 @@ from __future__ import annotations import logging from agent.i18n import t -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType # Log-record parity with gateway/run.py and the origin module. logger = logging.getLogger("gateway.run") diff --git a/gateway/slash_commands_model.py b/gateway/slash_commands_model.py index 3024f6380d..d39e865ea8 100644 --- a/gateway/slash_commands_model.py +++ b/gateway/slash_commands_model.py @@ -15,7 +15,7 @@ import logging from typing import Any, Optional from agent.i18n import t -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from hermes_cli.config import atomic_config_write, clear_model_endpoint_credentials from utils import base_url_host_matches diff --git a/gateway/slash_commands_session.py b/gateway/slash_commands_session.py index 9d60d660e6..8ed5882274 100644 --- a/gateway/slash_commands_session.py +++ b/gateway/slash_commands_session.py @@ -17,7 +17,8 @@ from typing import Optional, Union from agent.i18n import t from agent.turn_context import extract_api_content_sidecar from gateway.config import Platform -from gateway.platforms.base import EphemeralReply, MessageEvent, MessageType +from gateway.platforms.base import EphemeralReply +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key, is_shared_multi_user_session from gateway.session_transcript import TranscriptReadError from gateway.slash_commands_status import HISTORY_UNREADABLE diff --git a/gateway/slash_commands_status.py b/gateway/slash_commands_status.py index e449018c23..de26ffa739 100644 --- a/gateway/slash_commands_status.py +++ b/gateway/slash_commands_status.py @@ -14,7 +14,7 @@ from typing import Any from agent.account_usage import fetch_account_usage, render_account_usage_lines from agent.i18n import t from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session_transcript import TranscriptReadError # Log-record parity with gateway/run.py and the origin module. diff --git a/gateway/wake.py b/gateway/wake.py index 6c383a46e8..08b05396bc 100644 --- a/gateway/wake.py +++ b/gateway/wake.py @@ -43,7 +43,7 @@ async def deliver_wake(adapter: Any, *, text: str, session_id: str = "", source: if adapter_supports_push(adapter): if source is None: raise ValueError("deliver_wake: push-capable adapter requires a SessionSource") - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType synth_event = MessageEvent(text=text, message_type=MessageType.TEXT, source=source, internal=True) await adapter.handle_message(synth_event) return diff --git a/plugins/platforms/a2a/adapter.py b/plugins/platforms/a2a/adapter.py index a9e8b1100c..7a0af6dc03 100644 --- a/plugins/platforms/a2a/adapter.py +++ b/plugins/platforms/a2a/adapter.py @@ -23,7 +23,8 @@ from concurrent.futures import TimeoutError as FuturesTimeout from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from typing import Any, Dict, Optional -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, ProcessingOutcome, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from gateway.config import Platform from gateway.platforms._shared import coerce_port as _to_int, profile_scoped as _profile_scoped diff --git a/plugins/platforms/buzz/adapter.py b/plugins/platforms/buzz/adapter.py index 3a8328d0af..2d0533877e 100644 --- a/plugins/platforms/buzz/adapter.py +++ b/plugins/platforms/buzz/adapter.py @@ -187,8 +187,9 @@ def _scoped_platform_setting(env_name, extra, key): logger = logging.getLogger(__name__) from gateway.platforms.base import ( - BasePlatformAdapter, CachedMedia, SendResult, MessageEvent, MessageType, cache_media_bytes_async, + BasePlatformAdapter, CachedMedia, SendResult, cache_media_bytes_async, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.config import Platform diff --git a/plugins/platforms/dingtalk/adapter.py b/plugins/platforms/dingtalk/adapter.py index 46049d0211..a8f8452b32 100644 --- a/plugins/platforms/dingtalk/adapter.py +++ b/plugins/platforms/dingtalk/adapter.py @@ -48,7 +48,8 @@ except Exception: 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.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret from plugins.platforms.dingtalk.inbound import collect_download_codes, extract_media, extract_text @@ -764,7 +765,7 @@ EXT_MAP = { _PLUGIN_COMPAT_LAZY = { 'DINGTALK_TYPE_MAPPING': ('plugins.platforms.dingtalk.inbound', 'DINGTALK_TYPE_MAPPING'), - 'MessageType': ('gateway.platforms.base', 'MessageType'), + 'MessageType': ('gateway.platforms.event', 'MessageType'), } diff --git a/plugins/platforms/dingtalk/inbound.py b/plugins/platforms/dingtalk/inbound.py index 83a79d19cc..8148a8bc63 100644 --- a/plugins/platforms/dingtalk/inbound.py +++ b/plugins/platforms/dingtalk/inbound.py @@ -3,7 +3,7 @@ import json from typing import Any, List, Optional, Tuple -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType # DingTalk rich-text item type → runtime content type DINGTALK_TYPE_MAPPING = {"picture": "image", "voice": "audio"} diff --git a/plugins/platforms/discord/adapter.py b/plugins/platforms/discord/adapter.py index 3dc84d7378..32d754f8bd 100644 --- a/plugins/platforms/discord/adapter.py +++ b/plugins/platforms/discord/adapter.py @@ -261,11 +261,12 @@ from gateway.platforms.helpers import ( ) from utils import atomic_json_write, env_float from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, ProcessingOutcome, SendResult, + BasePlatformAdapter, SendResult, cache_image_from_url, cache_image_from_bytes_async, cache_audio_from_url, cache_audio_from_bytes_async, cache_document_from_bytes_async, SUPPORTED_DOCUMENT_TYPES, _TEXT_INJECT_EXTENSIONS, _prefix_within_utf16_limit, utf16_len, validate_inbound_media_size, ) +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from tools.url_safety import is_safe_url from gateway.platforms._shared import profile_scoped as _profile_scoped_config_load diff --git a/plugins/platforms/email/adapter.py b/plugins/platforms/email/adapter.py index 59b6e38273..18256ac192 100644 --- a/plugins/platforms/email/adapter.py +++ b/plugins/platforms/email/adapter.py @@ -21,8 +21,11 @@ from email import encoders from pathlib import Path from typing import Any, Dict, List, Optional, Tuple -from gateway.platforms.base import (BasePlatformAdapter, MessageEvent, MessageType, SendResult, - cache_document_from_bytes, cache_image_from_bytes) +from gateway.platforms.base import ( + BasePlatformAdapter, SendResult, + cache_document_from_bytes, cache_image_from_bytes, +) +from gateway.platforms.event import MessageEvent, MessageType from gateway.config import Platform, PlatformConfig from utils import is_truthy_value from gateway.platforms._shared import get_scoped_secret as _get_secret, coerce_port diff --git a/plugins/platforms/feishu/adapter.py b/plugins/platforms/feishu/adapter.py index 7614366cb7..eb48876caf 100644 --- a/plugins/platforms/feishu/adapter.py +++ b/plugins/platforms/feishu/adapter.py @@ -82,10 +82,11 @@ FEISHU_WEBHOOK_AVAILABLE = aiohttp is not None from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, ProcessingOutcome, SendResult, + BasePlatformAdapter, SendResult, SUPPORTED_DOCUMENT_TYPES, cache_document_from_bytes_async, cache_image_from_url, cache_audio_from_bytes_async, cache_image_from_bytes_async, ) +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from gateway.status import acquire_scoped_lock, release_scoped_lock from hermes_constants import get_hermes_home from utils import atomic_json_write, env_float, env_int diff --git a/plugins/platforms/feishu/feishu_meeting_invite.py b/plugins/platforms/feishu/feishu_meeting_invite.py index 58c0b2ef1e..99e9c42dd0 100644 --- a/plugins/platforms/feishu/feishu_meeting_invite.py +++ b/plugins/platforms/feishu/feishu_meeting_invite.py @@ -9,7 +9,7 @@ from dataclasses import dataclass from types import SimpleNamespace from typing import Any, Dict, Optional -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType logger = logging.getLogger(__name__) diff --git a/plugins/platforms/google_chat/adapter.py b/plugins/platforms/google_chat/adapter.py index accfa1b263..6d664f4fb8 100644 --- a/plugins/platforms/google_chat/adapter.py +++ b/plugins/platforms/google_chat/adapter.py @@ -124,10 +124,11 @@ from gateway.config import Platform, PlatformConfig Platform("google_chat") from gateway.platforms.helpers import MessageDeduplicator from gateway.platforms.base import ( - gateway_trust_env, BasePlatformAdapter, MessageEvent, MessageType, ProcessingOutcome, SendResult, + gateway_trust_env, BasePlatformAdapter, SendResult, cache_audio_from_bytes_async, cache_document_from_bytes_async, cache_image_from_bytes_async, cache_video_from_bytes_async, ) +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome # Pinned to the legacy module path so operator log filters keep matching. logger = logging.getLogger("gateway.platforms.google_chat") diff --git a/plugins/platforms/homeassistant/adapter.py b/plugins/platforms/homeassistant/adapter.py index 47ceb99316..f1acc42329 100644 --- a/plugins/platforms/homeassistant/adapter.py +++ b/plugins/platforms/homeassistant/adapter.py @@ -20,7 +20,8 @@ except ImportError: aiohttp = None # type: ignore[assignment] from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import gateway_trust_env, BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import gateway_trust_env, BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret logger = logging.getLogger(__name__) diff --git a/plugins/platforms/irc/adapter.py b/plugins/platforms/irc/adapter.py index 8413ff34eb..775ddd3407 100644 --- a/plugins/platforms/irc/adapter.py +++ b/plugins/platforms/irc/adapter.py @@ -16,7 +16,8 @@ import time from typing import Any, Dict, List, Optional from gateway.platforms._shared import coerce_port, get_scoped_secret as _get_scoped_secret -from gateway.platforms.base import BasePlatformAdapter, SendResult, MessageEvent, MessageType +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.config import Platform diff --git a/plugins/platforms/line/adapter.py b/plugins/platforms/line/adapter.py index 42237b963b..6c0dfe08da 100644 --- a/plugins/platforms/line/adapter.py +++ b/plugins/platforms/line/adapter.py @@ -35,9 +35,11 @@ from urllib.parse import quote as _urlquote from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret from gateway.platforms.base import ( - gateway_trust_env, BasePlatformAdapter, MessageEvent, MessageType, SendResult, + gateway_trust_env, BasePlatformAdapter, SendResult, cache_audio_from_bytes_async, cache_document_from_bytes_async, cache_image_from_bytes_async, - cache_video_from_bytes_async) + cache_video_from_bytes_async, +) +from gateway.platforms.event import MessageEvent, MessageType from gateway.config import Platform logger = logging.getLogger(__name__) diff --git a/plugins/platforms/matrix/adapter.py b/plugins/platforms/matrix/adapter.py index f9874e5ead..4875458cda 100644 --- a/plugins/platforms/matrix/adapter.py +++ b/plugins/platforms/matrix/adapter.py @@ -58,8 +58,10 @@ except ImportError: from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( - gateway_trust_env, BasePlatformAdapter, MessageEvent, MessageType, ProcessingOutcome, - SendResult, resolve_proxy_url, proxy_kwargs_for_aiohttp, _ssrf_redirect_guard) + gateway_trust_env, BasePlatformAdapter, + SendResult, resolve_proxy_url, proxy_kwargs_for_aiohttp, _ssrf_redirect_guard, +) +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from gateway.platforms.helpers import ThreadParticipationTracker logger = logging.getLogger(__name__) diff --git a/plugins/platforms/mattermost/adapter.py b/plugins/platforms/mattermost/adapter.py index 95d48719c6..af114ec27d 100644 --- a/plugins/platforms/mattermost/adapter.py +++ b/plugins/platforms/mattermost/adapter.py @@ -22,7 +22,8 @@ from typing import Any, Dict, List, Optional, Tuple from gateway.config import Platform, PlatformConfig from gateway.platforms.helpers import MessageDeduplicator -from gateway.platforms.base import gateway_trust_env, BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import gateway_trust_env, BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret, profile_scoped as _profile_scoped_config_load logger = logging.getLogger(__name__) diff --git a/plugins/platforms/ntfy/adapter.py b/plugins/platforms/ntfy/adapter.py index db7d12ea24..b2a8614822 100644 --- a/plugins/platforms/ntfy/adapter.py +++ b/plugins/platforms/ntfy/adapter.py @@ -25,7 +25,8 @@ except ImportError: httpx = None # type: ignore[assignment] from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret logger = logging.getLogger(__name__) diff --git a/plugins/platforms/photon/adapter.py b/plugins/platforms/photon/adapter.py index 64e7553fcb..a9659dae2c 100644 --- a/plugins/platforms/photon/adapter.py +++ b/plugins/platforms/photon/adapter.py @@ -38,7 +38,8 @@ else: from gateway.config import Platform, PlatformConfig from gateway.platforms._shared import coerce_port as _coerce_port from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.platforms.helpers import compile_mention_patterns, strip_markdown from .auth import load_project_credentials @@ -1623,7 +1624,7 @@ def register(ctx) -> None: _PLUGIN_COMPAT_LAZY = { - 'ProcessingOutcome': ('gateway.platforms.base', 'ProcessingOutcome'), + 'ProcessingOutcome': ('gateway.platforms.event', 'ProcessingOutcome'), 'resolve_sidecar_dir': ('plugins.platforms.photon.sidecar_paths', 'resolve_sidecar_dir'), } diff --git a/plugins/platforms/raft/adapter.py b/plugins/platforms/raft/adapter.py index 9f38281eb9..7a7ed4c395 100644 --- a/plugins/platforms/raft/adapter.py +++ b/plugins/platforms/raft/adapter.py @@ -37,7 +37,8 @@ except ImportError: sys.path.insert(0, str(_Path(__file__).resolve().parents[3])) from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult, merge_pending_message_event +from gateway.platforms.base import BasePlatformAdapter, SendResult, merge_pending_message_event +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import build_session_key from gateway.platforms._shared import coerce_port, profile_scoped as _profile_scoped diff --git a/plugins/platforms/simplex/adapter.py b/plugins/platforms/simplex/adapter.py index 4106683b21..3bf900f093 100644 --- a/plugins/platforms/simplex/adapter.py +++ b/plugins/platforms/simplex/adapter.py @@ -26,7 +26,8 @@ from urllib.parse import unquote from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult, cache_image_from_url +from gateway.platforms.base import BasePlatformAdapter, SendResult, cache_image_from_url +from gateway.platforms.event import MessageEvent, MessageType logger = logging.getLogger(__name__) diff --git a/plugins/platforms/slack/adapter.py b/plugins/platforms/slack/adapter.py index 173647d4dd..03b016f6f8 100644 --- a/plugins/platforms/slack/adapter.py +++ b/plugins/platforms/slack/adapter.py @@ -36,10 +36,12 @@ from agent.secret_scope import UnscopedSecretError, get_secret from gateway.config import Platform, PlatformConfig from gateway.platforms.helpers import MessageDeduplicator from gateway.platforms.base import ( - gateway_trust_env, BasePlatformAdapter, MessageEvent, MessageType, ProcessingOutcome, + gateway_trust_env, BasePlatformAdapter, SendResult, SUPPORTED_DOCUMENT_TYPES, SUPPORTED_VIDEO_TYPES, _TEXT_INJECT_EXTENSIONS, is_host_excluded_by_no_proxy, resolve_proxy_url, safe_url_for_log, _ssrf_redirect_guard, - cache_document_from_bytes_async, cache_video_from_bytes_async) + cache_document_from_bytes_async, cache_video_from_bytes_async, +) +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome try: # sibling module; support both package and flat plugin-dir import from .block_kit import render_blocks, sanitize_blocks diff --git a/plugins/platforms/teams/adapter.py b/plugins/platforms/teams/adapter.py index a596f1142b..41b441df30 100644 --- a/plugins/platforms/teams/adapter.py +++ b/plugins/platforms/teams/adapter.py @@ -55,8 +55,9 @@ HttpMethod = str # type: ignore[assignment,misc] from gateway.config import Platform, PlatformConfig from gateway.platforms.helpers import MessageDeduplicator from gateway.platforms.base import ( - gateway_trust_env, BasePlatformAdapter, MessageEvent, MessageType, SendResult, cache_image_from_url, cache_media_bytes_async, + gateway_trust_env, BasePlatformAdapter, SendResult, cache_image_from_url, cache_media_bytes_async, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.platforms._shared import coerce_port, get_scoped_secret as _get_scoped_secret logger = logging.getLogger(__name__) diff --git a/plugins/platforms/telegram/adapter.py b/plugins/platforms/telegram/adapter.py index 5149facc72..cfd4816cf5 100644 --- a/plugins/platforms/telegram/adapter.py +++ b/plugins/platforms/telegram/adapter.py @@ -142,9 +142,11 @@ sys.path.insert(0, str(_Path(__file__).resolve().parents[3])) from gateway.authz_mixin import _coerce_allow_set from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, ProcessingOutcome, SendResult, classify_send_error, + BasePlatformAdapter, SendResult, classify_send_error, cache_image_from_bytes_async, cache_audio_from_bytes_async, cache_video_from_bytes_async, resolve_proxy_url, SUPPORTED_VIDEO_TYPES, - SUPPORTED_DOCUMENT_TYPES, SUPPORTED_IMAGE_DOCUMENT_TYPES, _TEXT_INJECT_EXTENSIONS, utf16_len) + SUPPORTED_DOCUMENT_TYPES, SUPPORTED_IMAGE_DOCUMENT_TYPES, _TEXT_INJECT_EXTENSIONS, utf16_len, +) +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from plugins.platforms.telegram.telegram_ids import normalize_telegram_chat_id from plugins.platforms.telegram.telegram_network import ( SEED_FALLBACK_IPS, TelegramFallbackTransport, discover_fallback_ips, parse_fallback_ip_env, tcp_keepalive_socket_options) diff --git a/plugins/platforms/wecom/adapter.py b/plugins/platforms/wecom/adapter.py index 383d42aa60..afe198b738 100644 --- a/plugins/platforms/wecom/adapter.py +++ b/plugins/platforms/wecom/adapter.py @@ -28,7 +28,8 @@ HTTPX_AVAILABLE = httpx is not None from gateway.config import Platform, PlatformConfig from gateway.platforms.helpers import MessageDeduplicator -from gateway.platforms.base import gateway_trust_env, BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import gateway_trust_env, BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from utils import env_float from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret diff --git a/plugins/platforms/wecom/callback_adapter.py b/plugins/platforms/wecom/callback_adapter.py index 505b75a313..6fd03e05cd 100644 --- a/plugins/platforms/wecom/callback_adapter.py +++ b/plugins/platforms/wecom/callback_adapter.py @@ -32,7 +32,8 @@ except ImportError: HTTPX_AVAILABLE = False from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from plugins.platforms.wecom.wecom_crypto import WXBizMsgCrypt, WeComCryptoError logger = logging.getLogger(__name__) diff --git a/plugins/platforms/whatsapp/adapter.py b/plugins/platforms/whatsapp/adapter.py index 79c02ba07e..7ce812384d 100644 --- a/plugins/platforms/whatsapp/adapter.py +++ b/plugins/platforms/whatsapp/adapter.py @@ -173,8 +173,9 @@ from gateway.config import Platform, PlatformConfig from gateway.platforms.whatsapp_common import WhatsAppBehaviorMixin from gateway.whatsapp_identity import to_whatsapp_jid from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, SendResult, SUPPORTED_DOCUMENT_TYPES, cache_image_from_url, cache_audio_from_url, + BasePlatformAdapter, SendResult, SUPPORTED_DOCUMENT_TYPES, cache_image_from_url, cache_audio_from_url, ) +from gateway.platforms.event import MessageEvent, MessageType from utils import env_int diff --git a/tests/e2e/conftest.py b/tests/e2e/conftest.py index f8585878dc..577d0c13e2 100644 --- a/tests/e2e/conftest.py +++ b/tests/e2e/conftest.py @@ -23,7 +23,8 @@ if TYPE_CHECKING: from gateway.run import GatewayRunner from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, SendResult +from gateway.platforms.base import SendResult +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key E2E_MESSAGE_SETTLE_DELAY = 0.3 diff --git a/tests/gateway/relay/stub_connector.py b/tests/gateway/relay/stub_connector.py index 3f55cadca2..f74f5f659b 100644 --- a/tests/gateway/relay/stub_connector.py +++ b/tests/gateway/relay/stub_connector.py @@ -15,7 +15,7 @@ from __future__ import annotations from typing import Any, Dict, List, Optional -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.relay.descriptor import CapabilityDescriptor from gateway.relay.transport import InboundHandler diff --git a/tests/gateway/relay/test_relay_adapter.py b/tests/gateway/relay/test_relay_adapter.py index e821d7b0a6..09d3c90109 100644 --- a/tests/gateway/relay/test_relay_adapter.py +++ b/tests/gateway/relay/test_relay_adapter.py @@ -109,7 +109,7 @@ class _CaptureTransport: def _make_event(chat_id="chan-1", scope_id="scope-9"): - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource src = SessionSource( @@ -123,7 +123,7 @@ def _make_event(chat_id="chan-1", scope_id="scope-9"): def _make_dm_event(chat_id="dm-1", user_id="user-42"): """An inbound DM: no scope_id, carries the authentic author user_id.""" - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource src = SessionSource( @@ -144,7 +144,7 @@ def _make_scoped_event_with_author( guild scope_id and an author). Used to prove the adapter re-attaches BOTH discriminators so the connector can fall back author-first when the guild has no route row (managed agents join guilds dynamically).""" - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource src = SessionSource( @@ -226,7 +226,7 @@ async def test_send_typing_tags_egress_platform(): """Phase 1.5: a multi-platform gateway must egress typing through the platform the chat lives on, exactly like send() — the underlying platform learned from the inbound event tags the frame.""" - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource t = _CaptureTransport() diff --git a/tests/gateway/relay/test_relay_inbound_dedupe.py b/tests/gateway/relay/test_relay_inbound_dedupe.py index 008540a033..9f7118831d 100644 --- a/tests/gateway/relay/test_relay_inbound_dedupe.py +++ b/tests/gateway/relay/test_relay_inbound_dedupe.py @@ -18,7 +18,8 @@ import asyncio import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, SessionSource +from gateway.platforms.base import SessionSource +from gateway.platforms.event import MessageEvent from gateway.relay.adapter import RelayAdapter from gateway.relay.descriptor import CONTRACT_VERSION, CapabilityDescriptor from tests.gateway.relay.stub_connector import StubConnector diff --git a/tests/gateway/relay/test_relay_interactive.py b/tests/gateway/relay/test_relay_interactive.py index 853716d40c..4d1acbb31f 100644 --- a/tests/gateway/relay/test_relay_interactive.py +++ b/tests/gateway/relay/test_relay_interactive.py @@ -25,7 +25,7 @@ from typing import Any, Dict, Optional import pytest from gateway.config import PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, ProcessingOutcome +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from gateway.relay.adapter import RelayAdapter from gateway.relay.descriptor import CONTRACT_VERSION, CapabilityDescriptor from gateway.session import SessionSource diff --git a/tests/gateway/relay/test_relay_media.py b/tests/gateway/relay/test_relay_media.py index 05b8fdd4db..c78cf52766 100644 --- a/tests/gateway/relay/test_relay_media.py +++ b/tests/gateway/relay/test_relay_media.py @@ -136,7 +136,7 @@ async def test_op_gating_falls_back_when_not_advertised(tmp_path: Path): def _make_event(media_urls): - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource return MessageEvent( diff --git a/tests/gateway/relay/test_relay_multiplatform.py b/tests/gateway/relay/test_relay_multiplatform.py index 2302f2b09a..d46d58912a 100644 --- a/tests/gateway/relay/test_relay_multiplatform.py +++ b/tests/gateway/relay/test_relay_multiplatform.py @@ -100,7 +100,7 @@ def test_self_provision_loops_per_platform(monkeypatch): async def test_adapter_stamps_per_frame_platform_from_inbound(monkeypatch): """An inbound from a concrete platform makes the reply egress tagged for it.""" from gateway.config import Platform, PlatformConfig - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from gateway.relay.adapter import RelayAdapter from gateway.relay.descriptor import CONTRACT_VERSION, CapabilityDescriptor from gateway.session import SessionSource diff --git a/tests/gateway/relay/test_relay_per_platform_caps.py b/tests/gateway/relay/test_relay_per_platform_caps.py index 20ac1df3e9..8d0cc04df6 100644 --- a/tests/gateway/relay/test_relay_per_platform_caps.py +++ b/tests/gateway/relay/test_relay_per_platform_caps.py @@ -27,7 +27,7 @@ from typing import Any, Dict, List, Optional import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.relay.adapter import RelayAdapter from gateway.relay.descriptor import CONTRACT_VERSION, CapabilityDescriptor from gateway.session import SessionSource diff --git a/tests/gateway/relay/test_relay_roundtrip.py b/tests/gateway/relay/test_relay_roundtrip.py index 430350b518..cbdaca12b3 100644 --- a/tests/gateway/relay/test_relay_roundtrip.py +++ b/tests/gateway/relay/test_relay_roundtrip.py @@ -15,7 +15,7 @@ from __future__ import annotations import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key from gateway.relay.adapter import RelayAdapter from gateway.relay.descriptor import CONTRACT_VERSION, CapabilityDescriptor diff --git a/tests/gateway/relay/test_relay_roundtrip_telegram.py b/tests/gateway/relay/test_relay_roundtrip_telegram.py index 07ca273ce7..082e7d7bd6 100644 --- a/tests/gateway/relay/test_relay_roundtrip_telegram.py +++ b/tests/gateway/relay/test_relay_roundtrip_telegram.py @@ -22,7 +22,7 @@ from __future__ import annotations import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key from gateway.relay.adapter import RelayAdapter from gateway.relay.descriptor import CONTRACT_VERSION, CapabilityDescriptor diff --git a/tests/gateway/relay/test_relay_slack_dm_streaming.py b/tests/gateway/relay/test_relay_slack_dm_streaming.py index 9969b73957..31651f61da 100644 --- a/tests/gateway/relay/test_relay_slack_dm_streaming.py +++ b/tests/gateway/relay/test_relay_slack_dm_streaming.py @@ -24,7 +24,7 @@ from __future__ import annotations import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.relay.adapter import RelayAdapter from gateway.relay.descriptor import CONTRACT_VERSION, CapabilityDescriptor from gateway.session import SessionSource diff --git a/tests/gateway/relay/test_relay_slack_prompt_dm_root.py b/tests/gateway/relay/test_relay_slack_prompt_dm_root.py index 466fd10071..37dbef261f 100644 --- a/tests/gateway/relay/test_relay_slack_prompt_dm_root.py +++ b/tests/gateway/relay/test_relay_slack_prompt_dm_root.py @@ -28,7 +28,7 @@ from __future__ import annotations import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.relay.adapter import RelayAdapter from gateway.relay.descriptor import CONTRACT_VERSION, CapabilityDescriptor from gateway.session import SessionSource diff --git a/tests/gateway/relay/test_relay_slack_unfurl.py b/tests/gateway/relay/test_relay_slack_unfurl.py index dfa542b6b8..c44366bdff 100644 --- a/tests/gateway/relay/test_relay_slack_unfurl.py +++ b/tests/gateway/relay/test_relay_slack_unfurl.py @@ -61,7 +61,7 @@ def _slack_adapter(extra): def _mark_slack_chat(a, chat_id="chan-1"): - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource src = SessionSource( @@ -128,7 +128,7 @@ class TestSendStampsUnfurl: async def test_non_slack_chat_never_stamped(self): a = _slack_adapter({"slack": {"unfurl_links": False}}) # A chat mapped to discord, not slack, must not carry the hint. - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource src = SessionSource( diff --git a/tests/gateway/relay/test_wire_voice_media.py b/tests/gateway/relay/test_wire_voice_media.py index 833a3c51ad..e740091096 100644 --- a/tests/gateway/relay/test_wire_voice_media.py +++ b/tests/gateway/relay/test_wire_voice_media.py @@ -20,7 +20,7 @@ Pure unit tests: no socket, no websockets dependency. from __future__ import annotations -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType from gateway.relay.ws_transport import _event_from_wire @@ -329,7 +329,7 @@ class TestParallelArrayLengthInvariant: with the short list passed through.""" import asyncio - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from gateway.relay.adapter import RelayAdapter ev = MessageEvent(text="", message_type=MessageType.PHOTO) diff --git a/tests/gateway/test_25107_stale_base_url_api_mode.py b/tests/gateway/test_25107_stale_base_url_api_mode.py index cbfdbe79ca..91e68df554 100644 --- a/tests/gateway/test_25107_stale_base_url_api_mode.py +++ b/tests/gateway/test_25107_stale_base_url_api_mode.py @@ -29,7 +29,7 @@ import yaml import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_35994_reset_button_deadlock.py b/tests/gateway/test_35994_reset_button_deadlock.py index 2c22b4c3c0..903acfb4c4 100644 --- a/tests/gateway/test_35994_reset_button_deadlock.py +++ b/tests/gateway/test_35994_reset_button_deadlock.py @@ -22,7 +22,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_42039_duplicate_user_message.py b/tests/gateway/test_42039_duplicate_user_message.py index b00940d00d..4e058f58ef 100644 --- a/tests/gateway/test_42039_duplicate_user_message.py +++ b/tests/gateway/test_42039_duplicate_user_message.py @@ -23,7 +23,7 @@ import pytest import gateway.run as gateway_run from gateway.config import GatewayConfig, Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource from gateway.session_transcript import TranscriptReadError diff --git a/tests/gateway/test_73771_media_resend_dedup.py b/tests/gateway/test_73771_media_resend_dedup.py index 3c54e1c055..4d782c96a9 100644 --- a/tests/gateway/test_73771_media_resend_dedup.py +++ b/tests/gateway/test_73771_media_resend_dedup.py @@ -33,10 +33,9 @@ import pytest from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, SendResult, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner, _collect_auto_append_media_tags, _collect_history_media_paths from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_active_session_text_merge.py b/tests/gateway/test_active_session_text_merge.py index ac8df747c6..acba6f479e 100644 --- a/tests/gateway/test_active_session_text_merge.py +++ b/tests/gateway/test_active_session_text_merge.py @@ -32,10 +32,9 @@ sys.modules.setdefault("telegram.ext", types.ModuleType("telegram.ext")) from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, SendResult, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_approvals_command.py b/tests/gateway/test_approvals_command.py index 358a73cdaa..6978ae06c1 100644 --- a/tests/gateway/test_approvals_command.py +++ b/tests/gateway/test_approvals_command.py @@ -8,7 +8,7 @@ import yaml import gateway.run as gateway_run from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_approve_deny_commands.py b/tests/gateway/test_approve_deny_commands.py index fb9eb1ad0d..3aa2dc0766 100644 --- a/tests/gateway/test_approve_deny_commands.py +++ b/tests/gateway/test_approve_deny_commands.py @@ -17,7 +17,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_auto_voice_reply_format.py b/tests/gateway/test_auto_voice_reply_format.py index 824556ba21..bff36f0005 100644 --- a/tests/gateway/test_auto_voice_reply_format.py +++ b/tests/gateway/test_auto_voice_reply_format.py @@ -7,7 +7,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_background_command.py b/tests/gateway/test_background_command.py index c240abcdfc..54d34e64dd 100644 --- a/tests/gateway/test_background_command.py +++ b/tests/gateway/test_background_command.py @@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_base_auto_tts_output_format.py b/tests/gateway/test_base_auto_tts_output_format.py index 69af994f8f..9470dc579c 100644 --- a/tests/gateway/test_base_auto_tts_output_format.py +++ b/tests/gateway/test_base_auto_tts_output_format.py @@ -19,11 +19,10 @@ import pytest from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, SendResult, build_auto_tts_output_path, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key from tools.tts_tool import OPUS_VOICE_PLATFORMS diff --git a/tests/gateway/test_base_topic_sessions.py b/tests/gateway/test_base_topic_sessions.py index 4ddff51148..d0483c68b6 100644 --- a/tests/gateway/test_base_topic_sessions.py +++ b/tests/gateway/test_base_topic_sessions.py @@ -8,7 +8,8 @@ from unittest.mock import AsyncMock, patch import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, ProcessingOutcome, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_baseexception_turn_notify.py b/tests/gateway/test_baseexception_turn_notify.py index a40f76f1c9..8cb17fcf43 100644 --- a/tests/gateway/test_baseexception_turn_notify.py +++ b/tests/gateway/test_baseexception_turn_notify.py @@ -18,7 +18,8 @@ from __future__ import annotations import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType +from gateway.platforms.base import BasePlatformAdapter +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_branch_routing_columns.py b/tests/gateway/test_branch_routing_columns.py index 17c78b91eb..d5754e74be 100644 --- a/tests/gateway/test_branch_routing_columns.py +++ b/tests/gateway/test_branch_routing_columns.py @@ -28,7 +28,7 @@ from __future__ import annotations import pytest from gateway.config import GatewayConfig, Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource, SessionStore, build_session_key from hermes_state import AsyncSessionDB, SessionDB diff --git a/tests/gateway/test_bundles_command.py b/tests/gateway/test_bundles_command.py index 39ccf653df..c719a06db4 100644 --- a/tests/gateway/test_bundles_command.py +++ b/tests/gateway/test_bundles_command.py @@ -18,7 +18,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_busy_command.py b/tests/gateway/test_busy_command.py index dfeb806de2..e2aff70144 100644 --- a/tests/gateway/test_busy_command.py +++ b/tests/gateway/test_busy_command.py @@ -4,7 +4,8 @@ import pytest import gateway.run as gateway_run from gateway.config import Platform -from gateway.platforms.base import EphemeralReply, MessageEvent +from gateway.platforms.base import EphemeralReply +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_busy_session_ack.py b/tests/gateway/test_busy_session_ack.py index 03a18b8156..f28d847a9e 100644 --- a/tests/gateway/test_busy_session_ack.py +++ b/tests/gateway/test_busy_session_ack.py @@ -25,12 +25,11 @@ sys.modules.setdefault("telegram.constants", _tg.constants) sys.modules.setdefault("telegram.ext", types.ModuleType("telegram.ext")) from gateway.platforms.base import ( - MessageEvent, - MessageType, Platform, SessionSource, build_session_key, ) +from gateway.platforms.event import MessageEvent, MessageType # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_busy_session_auth_bypass.py b/tests/gateway/test_busy_session_auth_bypass.py index c7d4e32fb9..228600d6c4 100644 --- a/tests/gateway/test_busy_session_auth_bypass.py +++ b/tests/gateway/test_busy_session_auth_bypass.py @@ -26,11 +26,10 @@ sys.modules.setdefault("telegram.constants", _tg.constants) sys.modules.setdefault("telegram.ext", types.ModuleType("telegram.ext")) from gateway.platforms.base import ( - MessageEvent, - MessageType, SessionSource, build_session_key, ) +from gateway.platforms.event import MessageEvent, MessageType # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_buzz_adapter.py b/tests/gateway/test_buzz_adapter.py index bee8af29e3..e17f38d4e7 100644 --- a/tests/gateway/test_buzz_adapter.py +++ b/tests/gateway/test_buzz_adapter.py @@ -10,9 +10,10 @@ from types import SimpleNamespace import pytest from unittest.mock import AsyncMock, MagicMock -from gateway.platforms.base import CachedMedia, MessageType +from gateway.platforms.base import CachedMedia +from gateway.platforms.event import MessageType from tests.gateway._plugin_adapter_loader import load_plugin_adapter -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType # Load plugins/platforms/buzz/adapter.py under a unique module name # (plugin_adapter_buzz) so it cannot collide with other plugin adapters diff --git a/tests/gateway/test_cancel_background_drain.py b/tests/gateway/test_cancel_background_drain.py index 8f8c7694cd..4e45a6cab9 100644 --- a/tests/gateway/test_cancel_background_drain.py +++ b/tests/gateway/test_cancel_background_drain.py @@ -14,7 +14,8 @@ from unittest.mock import AsyncMock import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType +from gateway.platforms.base import BasePlatformAdapter +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_choice_picker.py b/tests/gateway/test_choice_picker.py index c8e6712ec0..5de1359beb 100644 --- a/tests/gateway/test_choice_picker.py +++ b/tests/gateway/test_choice_picker.py @@ -15,7 +15,8 @@ import yaml import gateway.run as gateway_run from gateway.config import Platform -from gateway.platforms.base import MessageEvent, SendResult +from gateway.platforms.base import SendResult +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_clarify_active_session_bypass.py b/tests/gateway/test_clarify_active_session_bypass.py index eef6eb75ea..8de7e4fde7 100644 --- a/tests/gateway/test_clarify_active_session_bypass.py +++ b/tests/gateway/test_clarify_active_session_bypass.py @@ -8,10 +8,9 @@ import pytest from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, SendResult, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_clarify_thread_followup_not_swallowed.py b/tests/gateway/test_clarify_thread_followup_not_swallowed.py index 210fd7bba8..9fd8359314 100644 --- a/tests/gateway/test_clarify_thread_followup_not_swallowed.py +++ b/tests/gateway/test_clarify_thread_followup_not_swallowed.py @@ -26,10 +26,9 @@ import pytest from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, SendResult, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource diff --git a/tests/gateway/test_command_bypass_active_session.py b/tests/gateway/test_command_bypass_active_session.py index 20b91c25e1..238351024f 100644 --- a/tests/gateway/test_command_bypass_active_session.py +++ b/tests/gateway/test_command_bypass_active_session.py @@ -17,7 +17,8 @@ import asyncio import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType +from gateway.platforms.base import BasePlatformAdapter +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_compress_command.py b/tests/gateway/test_compress_command.py index 4e502447b7..7797f232df 100644 --- a/tests/gateway/test_compress_command.py +++ b/tests/gateway/test_compress_command.py @@ -8,7 +8,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_compress_focus.py b/tests/gateway/test_compress_focus.py index 1513d6db28..e684ebe5ca 100644 --- a/tests/gateway/test_compress_focus.py +++ b/tests/gateway/test_compress_focus.py @@ -6,7 +6,7 @@ from unittest.mock import MagicMock, patch import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_compress_plugin_engine.py b/tests/gateway/test_compress_plugin_engine.py index 1e3a993404..673edb3eed 100644 --- a/tests/gateway/test_compress_plugin_engine.py +++ b/tests/gateway/test_compress_plugin_engine.py @@ -22,7 +22,7 @@ import pytest from agent.context_engine import ContextEngine from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_compress_preview.py b/tests/gateway/test_compress_preview.py index 9d07821279..3c066ac6f3 100644 --- a/tests/gateway/test_compress_preview.py +++ b/tests/gateway/test_compress_preview.py @@ -12,7 +12,7 @@ from unittest.mock import MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_compression_interrupt_demotion_56391.py b/tests/gateway/test_compression_interrupt_demotion_56391.py index 90bc29d9d5..9340171c5e 100644 --- a/tests/gateway/test_compression_interrupt_demotion_56391.py +++ b/tests/gateway/test_compression_interrupt_demotion_56391.py @@ -28,12 +28,11 @@ sys.modules.setdefault("telegram", _tg) sys.modules.setdefault("telegram.constants", _tg.constants) sys.modules.setdefault("telegram.ext", types.ModuleType("telegram.ext")) -from gateway.platforms.base import ( # noqa: E402 - MessageEvent, - MessageType, +from gateway.platforms.base import ( SessionSource, build_session_key, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner, _AGENT_PENDING_SENTINEL # noqa: E402 diff --git a/tests/gateway/test_context_ref_expansion_runtime.py b/tests/gateway/test_context_ref_expansion_runtime.py index a25974e6af..6af4e3d51f 100644 --- a/tests/gateway/test_context_ref_expansion_runtime.py +++ b/tests/gateway/test_context_ref_expansion_runtime.py @@ -25,7 +25,7 @@ import pytest import gateway.run as gateway_run from agent.context_references import ContextReferenceResult from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_debug_command.py b/tests/gateway/test_debug_command.py index c0a3937fa3..89dce280f2 100644 --- a/tests/gateway/test_debug_command.py +++ b/tests/gateway/test_debug_command.py @@ -5,7 +5,7 @@ from unittest.mock import patch import pytest from gateway.config import GatewayConfig, Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_delivery_ledger_producer.py b/tests/gateway/test_delivery_ledger_producer.py index 3f339dc61d..f80983f37d 100644 --- a/tests/gateway/test_delivery_ledger_producer.py +++ b/tests/gateway/test_delivery_ledger_producer.py @@ -15,7 +15,8 @@ import pytest from gateway import delivery_ledger as dl from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource diff --git a/tests/gateway/test_destructive_slash_confirm.py b/tests/gateway/test_destructive_slash_confirm.py index d8cd990007..875fe28913 100644 --- a/tests/gateway/test_destructive_slash_confirm.py +++ b/tests/gateway/test_destructive_slash_confirm.py @@ -16,7 +16,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_diff_command.py b/tests/gateway/test_diff_command.py index 4da4ecfc45..c5eeee89e8 100644 --- a/tests/gateway/test_diff_command.py +++ b/tests/gateway/test_diff_command.py @@ -14,7 +14,7 @@ import pytest import gateway.run as gateway_run import tools.checkpoint_manager as cpm from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource pytestmark = pytest.mark.skipif( diff --git a/tests/gateway/test_dingtalk.py b/tests/gateway/test_dingtalk.py index ac1775cd16..9b0df15164 100644 --- a/tests/gateway/test_dingtalk.py +++ b/tests/gateway/test_dingtalk.py @@ -403,7 +403,7 @@ class TestExtractMedia: reset it to TEXT, dropping the voice note from the STT path (#38211, #38219).""" from plugins.platforms.dingtalk.adapter import DingTalkAdapter - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType msg = self._msg_with_rich_text( [{"type": "voice", "downloadCode": "dl_voice_rt"}] @@ -420,7 +420,7 @@ class TestExtractMedia: def test_image_no_filename_still_photo(self): """msgtype='image' without fileName → still PHOTO (MIME heuristic).""" from plugins.platforms.dingtalk.adapter import DingTalkAdapter - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType msg = MagicMock() msg.text = None diff --git a/tests/gateway/test_discord_attachment_download.py b/tests/gateway/test_discord_attachment_download.py index 5b9575ee91..90fcfc5c06 100644 --- a/tests/gateway/test_discord_attachment_download.py +++ b/tests/gateway/test_discord_attachment_download.py @@ -59,7 +59,7 @@ def _ensure_discord_mock(): _ensure_discord_mock() from plugins.platforms.discord.adapter import DiscordAdapter # noqa: E402 -from gateway.platforms.base import MessageType # noqa: E402 +from gateway.platforms.event import MessageType # noqa: E402 # Minimal valid image / audio / PDF bytes so the cache_*_from_bytes diff --git a/tests/gateway/test_discord_channel_prompts.py b/tests/gateway/test_discord_channel_prompts.py index a23070c95f..69b15444b6 100644 --- a/tests/gateway/test_discord_channel_prompts.py +++ b/tests/gateway/test_discord_channel_prompts.py @@ -30,7 +30,7 @@ def _ensure_discord_mock(): import gateway.run as gateway_run from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_discord_document_handling.py b/tests/gateway/test_discord_document_handling.py index bf70089405..8abc0f8e23 100644 --- a/tests/gateway/test_discord_document_handling.py +++ b/tests/gateway/test_discord_document_handling.py @@ -15,7 +15,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import PlatformConfig -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_discord_missed_message_backfill.py b/tests/gateway/test_discord_missed_message_backfill.py index 2e70830a7d..5ed8f3b819 100644 --- a/tests/gateway/test_discord_missed_message_backfill.py +++ b/tests/gateway/test_discord_missed_message_backfill.py @@ -11,7 +11,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, ProcessingOutcome +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome def _ensure_discord_mock(): diff --git a/tests/gateway/test_discord_pending_text_batch_shutdown.py b/tests/gateway/test_discord_pending_text_batch_shutdown.py index d89b65f58b..2ef1ba7bdf 100644 --- a/tests/gateway/test_discord_pending_text_batch_shutdown.py +++ b/tests/gateway/test_discord_pending_text_batch_shutdown.py @@ -8,7 +8,7 @@ from unittest.mock import MagicMock import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource diff --git a/tests/gateway/test_discord_reactions.py b/tests/gateway/test_discord_reactions.py index 718f173d95..c629302bec 100644 --- a/tests/gateway/test_discord_reactions.py +++ b/tests/gateway/test_discord_reactions.py @@ -8,7 +8,8 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, ProcessingOutcome, SendResult +from gateway.platforms.base import SendResult +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_dm_topics.py b/tests/gateway/test_dm_topics.py index f889f95c66..d1cc996101 100644 --- a/tests/gateway/test_dm_topics.py +++ b/tests/gateway/test_dm_topics.py @@ -369,7 +369,7 @@ def _make_mock_message(chat_id=111, chat_type="private", text="hello", thread_id def test_build_message_event_sets_auto_skill(): """When topic has a skill binding, auto_skill should be set on the event.""" - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType adapter = _make_adapter([ { @@ -391,7 +391,7 @@ def test_build_message_event_sets_auto_skill(): def test_build_message_event_no_auto_skill_without_binding(): """Topics without skill binding should have auto_skill=None.""" - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType adapter = _make_adapter([ { @@ -421,7 +421,7 @@ from telegram.constants import ChatType as _ChatType # noqa: E402 def test_group_topic_skill_binding(): """Group topic with skill config should set auto_skill on the event.""" - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType adapter = _make_adapter(group_topics_config=[ { @@ -449,7 +449,7 @@ def test_group_topic_skill_binding(): def test_group_topic_skill_binding_second_topic(): """A different thread_id in the same group should resolve its own skill.""" - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType adapter = _make_adapter(group_topics_config=[ { diff --git a/tests/gateway/test_document_context_note.py b/tests/gateway/test_document_context_note.py index 42f4e45a1d..12b456f14f 100644 --- a/tests/gateway/test_document_context_note.py +++ b/tests/gateway/test_document_context_note.py @@ -15,7 +15,7 @@ import importlib import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_duplicate_reply_suppression.py b/tests/gateway/test_duplicate_reply_suppression.py index 87a8f54644..59084e3872 100644 --- a/tests/gateway/test_duplicate_reply_suppression.py +++ b/tests/gateway/test_duplicate_reply_suppression.py @@ -20,9 +20,9 @@ import pytest from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, SendResult, ) +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_email.py b/tests/gateway/test_email.py index 271195daff..444ae94ea6 100644 --- a/tests/gateway/test_email.py +++ b/tests/gateway/test_email.py @@ -238,7 +238,7 @@ class TestDispatchMessage(unittest.TestCase): def test_image_attachment_sets_photo_type(self): """Email with image attachment should set message type to PHOTO.""" import asyncio - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType adapter = self._make_adapter() captured_events = [] diff --git a/tests/gateway/test_ephemeral_reply.py b/tests/gateway/test_ephemeral_reply.py index ce77792bfa..8e6a62872e 100644 --- a/tests/gateway/test_ephemeral_reply.py +++ b/tests/gateway/test_ephemeral_reply.py @@ -29,10 +29,9 @@ from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, EphemeralReply, - MessageEvent, - MessageType, SendResult, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource diff --git a/tests/gateway/test_external_drain_control.py b/tests/gateway/test_external_drain_control.py index 0b8050df8c..13348e2bf0 100644 --- a/tests/gateway/test_external_drain_control.py +++ b/tests/gateway/test_external_drain_control.py @@ -21,7 +21,7 @@ import pytest import gateway.drain_control as dc from gateway.run import GatewayRunner from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from tests.gateway.restart_test_helpers import make_restart_runner, make_restart_source diff --git a/tests/gateway/test_fast_command.py b/tests/gateway/test_fast_command.py index b8792ecce4..1d9a63514f 100644 --- a/tests/gateway/test_fast_command.py +++ b/tests/gateway/test_fast_command.py @@ -11,7 +11,7 @@ import yaml import gateway.run as gateway_run from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_feishu.py b/tests/gateway/test_feishu.py index f5f94c2fb7..24f6462991 100644 --- a/tests/gateway/test_feishu.py +++ b/tests/gateway/test_feishu.py @@ -13,7 +13,7 @@ from types import SimpleNamespace from typing import TYPE_CHECKING, Dict from unittest.mock import AsyncMock, Mock, patch -from gateway.platforms.base import ProcessingOutcome +from gateway.platforms.event import ProcessingOutcome if TYPE_CHECKING: from plugins.platforms.feishu.adapter import FeishuAdapter @@ -910,7 +910,7 @@ class TestAdapterBehavior(unittest.TestCase): @patch.dict(os.environ, {}, clear=True) def test_process_inbound_message_uses_event_sender_identity_only(self): from gateway.config import PlatformConfig - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType from plugins.platforms.feishu.adapter import FeishuAdapter adapter = FeishuAdapter(PlatformConfig()) @@ -963,7 +963,7 @@ class TestAdapterBehavior(unittest.TestCase): ) def test_text_batch_flushes_when_message_count_limit_is_hit(self): from gateway.config import PlatformConfig - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from plugins.platforms.feishu.adapter import FeishuAdapter from gateway.session import SessionSource @@ -1007,7 +1007,7 @@ class TestAdapterBehavior(unittest.TestCase): @patch.dict(os.environ, {}, clear=True) def test_media_batch_merges_rapid_photo_messages(self): from gateway.config import PlatformConfig - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from plugins.platforms.feishu.adapter import FeishuAdapter from gateway.session import SessionSource @@ -2287,7 +2287,7 @@ class TestFeishuProcessInboundMessage(unittest.TestCase): def test_non_command_message_with_mentions_injects_hint(self): - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType adapter = self._build_adapter() alice = SimpleNamespace( diff --git a/tests/gateway/test_feishu_meeting_invite.py b/tests/gateway/test_feishu_meeting_invite.py index d8e4725a64..505c23725f 100644 --- a/tests/gateway/test_feishu_meeting_invite.py +++ b/tests/gateway/test_feishu_meeting_invite.py @@ -5,7 +5,7 @@ import unittest from types import SimpleNamespace from unittest.mock import patch -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from plugins.platforms.feishu.feishu_meeting_invite import ( build_meeting_invite_prompt, handle_meeting_invited_event, diff --git a/tests/gateway/test_feishu_voice_message_type.py b/tests/gateway/test_feishu_voice_message_type.py index 37c68b13b4..ec7cc9cdc7 100644 --- a/tests/gateway/test_feishu_voice_message_type.py +++ b/tests/gateway/test_feishu_voice_message_type.py @@ -9,7 +9,7 @@ file attachment — so a Feishu voice note silently reached the agent as untranscribable audio. Follow-up to #28993 (Discord + DingTalk). """ -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType from plugins.platforms.feishu.adapter import FeishuAdapter, FeishuNormalizedMessage diff --git a/tests/gateway/test_fifo_overflow_rescue.py b/tests/gateway/test_fifo_overflow_rescue.py index e1f3efd110..a7f985137d 100644 --- a/tests/gateway/test_fifo_overflow_rescue.py +++ b/tests/gateway/test_fifo_overflow_rescue.py @@ -18,11 +18,10 @@ from unittest.mock import MagicMock from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, Platform, PlatformConfig, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner diff --git a/tests/gateway/test_first_turn_session_meta_rebaseline.py b/tests/gateway/test_first_turn_session_meta_rebaseline.py index a7f3e4fb38..0e90ff758f 100644 --- a/tests/gateway/test_first_turn_session_meta_rebaseline.py +++ b/tests/gateway/test_first_turn_session_meta_rebaseline.py @@ -43,7 +43,7 @@ import pytest import gateway.run as gateway_run from gateway.config import GatewayConfig, Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource diff --git a/tests/gateway/test_footer_command_mid_run.py b/tests/gateway/test_footer_command_mid_run.py index f970f59958..19d34a67c0 100644 --- a/tests/gateway/test_footer_command_mid_run.py +++ b/tests/gateway/test_footer_command_mid_run.py @@ -29,7 +29,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_gateway_command_dispatch_minimal.py b/tests/gateway/test_gateway_command_dispatch_minimal.py index 3aad22b844..d0a9b96593 100644 --- a/tests/gateway/test_gateway_command_dispatch_minimal.py +++ b/tests/gateway/test_gateway_command_dispatch_minimal.py @@ -5,7 +5,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_gateway_command_help.py b/tests/gateway/test_gateway_command_help.py index 773d218606..e7eba04c4c 100644 --- a/tests/gateway/test_gateway_command_help.py +++ b/tests/gateway/test_gateway_command_help.py @@ -3,7 +3,7 @@ import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_gateway_shutdown.py b/tests/gateway/test_gateway_shutdown.py index 0edb15ce1d..cd062ca447 100644 --- a/tests/gateway/test_gateway_shutdown.py +++ b/tests/gateway/test_gateway_shutdown.py @@ -6,7 +6,7 @@ import pytest import gateway.run as gateway_run from gateway.config import HomeChannel, Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.restart import DEFAULT_GATEWAY_POST_INTERRUPT_GRACE_TIMEOUT, GATEWAY_SERVICE_RESTART_EXIT_CODE from gateway.session import build_session_key from tests.gateway.restart_test_helpers import make_restart_runner, make_restart_source diff --git a/tests/gateway/test_gateway_silence_tokens.py b/tests/gateway/test_gateway_silence_tokens.py index 0af7eec226..a9f7ce445d 100644 --- a/tests/gateway/test_gateway_silence_tokens.py +++ b/tests/gateway/test_gateway_silence_tokens.py @@ -7,7 +7,7 @@ import pytest import gateway.run as gateway_run from gateway.config import GatewayConfig, Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource from gateway.response_filters import ( is_intentional_silence_agent_result, diff --git a/tests/gateway/test_goal_continuation_drain.py b/tests/gateway/test_goal_continuation_drain.py index 6a969c07e3..eb2309bc9f 100644 --- a/tests/gateway/test_goal_continuation_drain.py +++ b/tests/gateway/test_goal_continuation_drain.py @@ -22,7 +22,8 @@ import asyncio import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType +from gateway.platforms.base import BasePlatformAdapter +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_goal_max_turns_config.py b/tests/gateway/test_goal_max_turns_config.py index 3d3c81e3a0..96a101b4dd 100644 --- a/tests/gateway/test_goal_max_turns_config.py +++ b/tests/gateway/test_goal_max_turns_config.py @@ -4,7 +4,7 @@ import time import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource from hermes_cli import goals diff --git a/tests/gateway/test_goal_resume_restart.py b/tests/gateway/test_goal_resume_restart.py index 2fcf1f34c5..929976a9c8 100644 --- a/tests/gateway/test_goal_resume_restart.py +++ b/tests/gateway/test_goal_resume_restart.py @@ -22,7 +22,7 @@ from unittest.mock import MagicMock, patch import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource from hermes_cli import goals diff --git a/tests/gateway/test_goal_status_notice.py b/tests/gateway/test_goal_status_notice.py index ada6d2dc9a..35c1a5eff9 100644 --- a/tests/gateway/test_goal_status_notice.py +++ b/tests/gateway/test_goal_status_notice.py @@ -5,7 +5,7 @@ from types import SimpleNamespace import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource from hermes_cli.goals import CONTINUATION_PROMPT_TEMPLATE diff --git a/tests/gateway/test_google_chat.py b/tests/gateway/test_google_chat.py index cd97dfe68d..db425ec33d 100644 --- a/tests/gateway/test_google_chat.py +++ b/tests/gateway/test_google_chat.py @@ -129,7 +129,7 @@ import plugins.platforms.google_chat.adapter as _gc_mod # noqa: E402 _gc_mod.GOOGLE_CHAT_AVAILABLE = True -from gateway.platforms.base import MessageEvent, MessageType, ProcessingOutcome # noqa: E402 +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome # noqa: E402 from plugins.platforms.google_chat.adapter import ( # noqa: E402 GoogleChatAdapter, _is_google_owned_host, diff --git a/tests/gateway/test_image_input_routing_runtime.py b/tests/gateway/test_image_input_routing_runtime.py index 2d2fa4a44c..2368c5c063 100644 --- a/tests/gateway/test_image_input_routing_runtime.py +++ b/tests/gateway/test_image_input_routing_runtime.py @@ -1,7 +1,7 @@ import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_incomplete_gateway_turns.py b/tests/gateway/test_incomplete_gateway_turns.py index 6a372f3f64..76c94e7724 100644 --- a/tests/gateway/test_incomplete_gateway_turns.py +++ b/tests/gateway/test_incomplete_gateway_turns.py @@ -9,7 +9,8 @@ import pytest import gateway.run as gateway_run from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, ProcessingOutcome, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, ProcessingOutcome from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_internal_event_bypass_pairing.py b/tests/gateway/test_internal_event_bypass_pairing.py index d20f1c70e4..6c6b99a770 100644 --- a/tests/gateway/test_internal_event_bypass_pairing.py +++ b/tests/gateway/test_internal_event_bypass_pairing.py @@ -14,7 +14,7 @@ from unittest.mock import AsyncMock import pytest from gateway.config import GatewayConfig, Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.run import GatewayRunner from gateway.session import SessionSource from tools.process_registry import ProcessRegistry, ProcessSession diff --git a/tests/gateway/test_internal_event_never_interrupts_busy_session.py b/tests/gateway/test_internal_event_never_interrupts_busy_session.py index 4c219cac0f..0d0994d366 100644 --- a/tests/gateway/test_internal_event_never_interrupts_busy_session.py +++ b/tests/gateway/test_internal_event_never_interrupts_busy_session.py @@ -39,12 +39,11 @@ sys.modules.setdefault("telegram", _tg) sys.modules.setdefault("telegram.constants", _tg.constants) sys.modules.setdefault("telegram.ext", types.ModuleType("telegram.ext")) -from gateway.platforms.base import ( # noqa: E402 - MessageEvent, - MessageType, +from gateway.platforms.base import ( SessionSource, build_session_key, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner # noqa: E402 diff --git a/tests/gateway/test_internal_notification_marker_82888.py b/tests/gateway/test_internal_notification_marker_82888.py index d3f9301e31..bcec76bf9c 100644 --- a/tests/gateway/test_internal_notification_marker_82888.py +++ b/tests/gateway/test_internal_notification_marker_82888.py @@ -26,7 +26,7 @@ import pytest import gateway.run as gateway_run from gateway.config import GatewayConfig, Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource SESSION_KEY = "agent:main:telegram:group:-1001:12345" diff --git a/tests/gateway/test_interrupt_key_match.py b/tests/gateway/test_interrupt_key_match.py index f6e349fda1..79c39ee7bf 100644 --- a/tests/gateway/test_interrupt_key_match.py +++ b/tests/gateway/test_interrupt_key_match.py @@ -11,7 +11,8 @@ import asyncio import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_loop_command.py b/tests/gateway/test_loop_command.py index 19c9c88520..f52a0bfb60 100644 --- a/tests/gateway/test_loop_command.py +++ b/tests/gateway/test_loop_command.py @@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, Mock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource from hermes_cli import goals, loops diff --git a/tests/gateway/test_matrix.py b/tests/gateway/test_matrix.py index 4c02c9385b..d220036ac8 100644 --- a/tests/gateway/test_matrix.py +++ b/tests/gateway/test_matrix.py @@ -9,7 +9,7 @@ import pytest from unittest.mock import MagicMock, patch, AsyncMock from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType def _make_fake_mautrix(): @@ -1854,7 +1854,7 @@ class TestMatrixReactions: @pytest.mark.asyncio async def test_on_processing_complete_sends_check(self): - from gateway.platforms.base import MessageEvent, MessageType, ProcessingOutcome + from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome self.adapter._reactions_enabled = True self.adapter._reaction_redaction_delay_seconds = 0.01 diff --git a/tests/gateway/test_matrix_project_context_isolation.py b/tests/gateway/test_matrix_project_context_isolation.py index 3060769f67..d24ff3dbcc 100644 --- a/tests/gateway/test_matrix_project_context_isolation.py +++ b/tests/gateway/test_matrix_project_context_isolation.py @@ -11,7 +11,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from hermes_state import AsyncSessionDB from gateway.session import ( SessionContext, diff --git a/tests/gateway/test_matrix_voice.py b/tests/gateway/test_matrix_voice.py index ee7ad50ee9..d3af328865 100644 --- a/tests/gateway/test_matrix_voice.py +++ b/tests/gateway/test_matrix_voice.py @@ -18,7 +18,7 @@ try: except ImportError: pytest.skip("mautrix not installed", allow_module_level=True) -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_mattermost.py b/tests/gateway/test_mattermost.py index 9cb56073a8..af0501b102 100644 --- a/tests/gateway/test_mattermost.py +++ b/tests/gateway/test_mattermost.py @@ -6,7 +6,7 @@ import pytest from unittest.mock import MagicMock, patch, AsyncMock from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType from gateway.run import ( _resolve_gateway_display_bool, _resolve_progress_thread_id, diff --git a/tests/gateway/test_max_concurrent_sessions.py b/tests/gateway/test_max_concurrent_sessions.py index d3612698d2..740c00176a 100644 --- a/tests/gateway/test_max_concurrent_sessions.py +++ b/tests/gateway/test_max_concurrent_sessions.py @@ -7,7 +7,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner, _AGENT_PENDING_SENTINEL from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_mcp_reload_refreshes_cached_agents.py b/tests/gateway/test_mcp_reload_refreshes_cached_agents.py index 82dd53e5f2..ad4e54fb71 100644 --- a/tests/gateway/test_mcp_reload_refreshes_cached_agents.py +++ b/tests/gateway/test_mcp_reload_refreshes_cached_agents.py @@ -20,7 +20,7 @@ from unittest.mock import MagicMock, patch import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_mixed_attachment_routing.py b/tests/gateway/test_mixed_attachment_routing.py index f03fa3fb1e..a514cf8833 100644 --- a/tests/gateway/test_mixed_attachment_routing.py +++ b/tests/gateway/test_mixed_attachment_routing.py @@ -22,7 +22,8 @@ from types import SimpleNamespace import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, merge_pending_message_event +from gateway.platforms.base import merge_pending_message_event +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import ( GatewayRunner, _build_media_placeholder, diff --git a/tests/gateway/test_model_command_async_offload.py b/tests/gateway/test_model_command_async_offload.py index 9936461a33..ed973d8619 100644 --- a/tests/gateway/test_model_command_async_offload.py +++ b/tests/gateway/test_model_command_async_offload.py @@ -25,7 +25,7 @@ import pytest import gateway.slash_commands as slash_commands from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_model_command_context_offload.py b/tests/gateway/test_model_command_context_offload.py index 8b7868a528..1591c2b2e6 100644 --- a/tests/gateway/test_model_command_context_offload.py +++ b/tests/gateway/test_model_command_context_offload.py @@ -19,7 +19,7 @@ from unittest.mock import AsyncMock, MagicMock import gateway.slash_commands as slash_commands from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource diff --git a/tests/gateway/test_model_command_custom_providers.py b/tests/gateway/test_model_command_custom_providers.py index 85076716b7..5b32ab56d8 100644 --- a/tests/gateway/test_model_command_custom_providers.py +++ b/tests/gateway/test_model_command_custom_providers.py @@ -4,7 +4,7 @@ import yaml import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_model_command_expensive_confirm.py b/tests/gateway/test_model_command_expensive_confirm.py index eb62939f60..18fa58ce92 100644 --- a/tests/gateway/test_model_command_expensive_confirm.py +++ b/tests/gateway/test_model_command_expensive_confirm.py @@ -19,7 +19,7 @@ import pytest import yaml from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_model_command_flat_string_config.py b/tests/gateway/test_model_command_flat_string_config.py index 2c533a5fc9..3dc1d9b871 100644 --- a/tests/gateway/test_model_command_flat_string_config.py +++ b/tests/gateway/test_model_command_flat_string_config.py @@ -15,7 +15,7 @@ import yaml import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_model_command_profile_config.py b/tests/gateway/test_model_command_profile_config.py index 00fc9aa708..1f9552384e 100644 --- a/tests/gateway/test_model_command_profile_config.py +++ b/tests/gateway/test_model_command_profile_config.py @@ -5,7 +5,7 @@ from types import SimpleNamespace import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_model_command_request_overrides.py b/tests/gateway/test_model_command_request_overrides.py index f37b88d7e6..df0838dc1b 100644 --- a/tests/gateway/test_model_command_request_overrides.py +++ b/tests/gateway/test_model_command_request_overrides.py @@ -3,7 +3,7 @@ import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_model_picker_persist.py b/tests/gateway/test_model_picker_persist.py index 7f5c4c04a3..bcc24263c4 100644 --- a/tests/gateway/test_model_picker_persist.py +++ b/tests/gateway/test_model_picker_persist.py @@ -25,7 +25,7 @@ import yaml import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_model_switch_persistence.py b/tests/gateway/test_model_switch_persistence.py index 03926cb06f..ea0a175c1a 100644 --- a/tests/gateway/test_model_switch_persistence.py +++ b/tests/gateway/test_model_switch_persistence.py @@ -232,7 +232,7 @@ class TestOneTurnNeverPersisted: @staticmethod def _event(text): - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType return MessageEvent( text=text, diff --git a/tests/gateway/test_multiplex_busy_input_mode.py b/tests/gateway/test_multiplex_busy_input_mode.py index 8d28668bf8..e96b775070 100644 --- a/tests/gateway/test_multiplex_busy_input_mode.py +++ b/tests/gateway/test_multiplex_busy_input_mode.py @@ -9,12 +9,11 @@ import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, SendResult, SessionSource, build_session_key, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.profile_routing import ProfileRoute from gateway.run import GatewayRunner diff --git a/tests/gateway/test_multiplex_mcp_discovery.py b/tests/gateway/test_multiplex_mcp_discovery.py index ba586ae3f4..b0b83b696a 100644 --- a/tests/gateway/test_multiplex_mcp_discovery.py +++ b/tests/gateway/test_multiplex_mcp_discovery.py @@ -10,7 +10,7 @@ from unittest.mock import MagicMock import pytest from gateway.config import GatewayConfig, Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource from hermes_constants import get_hermes_home, hermes_home_key diff --git a/tests/gateway/test_multiplex_session_db_profile_scope.py b/tests/gateway/test_multiplex_session_db_profile_scope.py index ef9d13e5da..d532b081e6 100644 --- a/tests/gateway/test_multiplex_session_db_profile_scope.py +++ b/tests/gateway/test_multiplex_session_db_profile_scope.py @@ -33,7 +33,8 @@ from unittest.mock import MagicMock, patch import pytest from gateway.config import GatewayConfig -from gateway.platforms.base import MessageEvent, Platform, SessionSource +from gateway.platforms.base import Platform, SessionSource +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionStore from hermes_constants import ( get_hermes_home, diff --git a/tests/gateway/test_native_image_buffer_isolation.py b/tests/gateway/test_native_image_buffer_isolation.py index dbaa4350a4..20a9389cb5 100644 --- a/tests/gateway/test_native_image_buffer_isolation.py +++ b/tests/gateway/test_native_image_buffer_isolation.py @@ -1,7 +1,7 @@ import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_pending_drain_no_recursion.py b/tests/gateway/test_pending_drain_no_recursion.py index acedc6ae4b..1752fb23cd 100644 --- a/tests/gateway/test_pending_drain_no_recursion.py +++ b/tests/gateway/test_pending_drain_no_recursion.py @@ -28,9 +28,8 @@ import pytest from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_pending_drain_race.py b/tests/gateway/test_pending_drain_race.py index 479e769264..f550c4ed6d 100644 --- a/tests/gateway/test_pending_drain_race.py +++ b/tests/gateway/test_pending_drain_race.py @@ -29,9 +29,8 @@ import pytest from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_plaintext_approval_routing.py b/tests/gateway/test_plaintext_approval_routing.py index bbe5e58af5..6accafb937 100644 --- a/tests/gateway/test_plaintext_approval_routing.py +++ b/tests/gateway/test_plaintext_approval_routing.py @@ -19,7 +19,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource diff --git a/tests/gateway/test_platform_base.py b/tests/gateway/test_platform_base.py index f9d9c8897e..70b5ee2449 100644 --- a/tests/gateway/test_platform_base.py +++ b/tests/gateway/test_platform_base.py @@ -9,7 +9,6 @@ import pytest from gateway.platforms.base import ( BasePlatformAdapter, GATEWAY_SECRET_CAPTURE_UNSUPPORTED_MESSAGE, - MessageEvent, SendResult, cache_audio_from_bytes, cache_image_from_bytes, @@ -21,6 +20,7 @@ from gateway.platforms.base import ( _prefix_within_utf16_limit, cache_audio_from_bytes, ) +from gateway.platforms.event import MessageEvent def test_media_delivery_denies_encrypted_bitwarden_cache(tmp_path, monkeypatch): diff --git a/tests/gateway/test_plugin_message_injection.py b/tests/gateway/test_plugin_message_injection.py index da054a4c48..ed990550ed 100644 --- a/tests/gateway/test_plugin_message_injection.py +++ b/tests/gateway/test_plugin_message_injection.py @@ -12,10 +12,9 @@ import yaml from gateway.config import GatewayConfig, Platform from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, PlatformConfig, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionEntry, SessionSource, SessionStore, build_session_key from hermes_cli.plugins import PluginContext, PluginManager, PluginManifest diff --git a/tests/gateway/test_post_stream_media_delivery.py b/tests/gateway/test_post_stream_media_delivery.py index bbb1f7c6fe..d249791e8e 100644 --- a/tests/gateway/test_post_stream_media_delivery.py +++ b/tests/gateway/test_post_stream_media_delivery.py @@ -18,7 +18,8 @@ from unittest.mock import AsyncMock import pytest from gateway.config import Platform -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_pre_gateway_dispatch.py b/tests/gateway/test_pre_gateway_dispatch.py index a52194e51b..7c6ccf5e21 100644 --- a/tests/gateway/test_pre_gateway_dispatch.py +++ b/tests/gateway/test_pre_gateway_dispatch.py @@ -11,7 +11,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_priority_path_compression_demotion_56391.py b/tests/gateway/test_priority_path_compression_demotion_56391.py index 4c8303988a..4cd1a47c95 100644 --- a/tests/gateway/test_priority_path_compression_demotion_56391.py +++ b/tests/gateway/test_priority_path_compression_demotion_56391.py @@ -32,7 +32,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_profile_resolution.py b/tests/gateway/test_profile_resolution.py index ee827ca262..051a0a907e 100644 --- a/tests/gateway/test_profile_resolution.py +++ b/tests/gateway/test_profile_resolution.py @@ -10,7 +10,8 @@ from gateway.session import SessionSource, build_session_key from gateway.run import GatewayRunner from gateway.profile_routing import ProfileRoute, ProfileRouteRejected from gateway.config import GatewayConfig, Platform -from gateway.platforms.base import BasePlatformAdapter, MessageEvent +from gateway.platforms.base import BasePlatformAdapter +from gateway.platforms.event import MessageEvent @pytest.fixture diff --git a/tests/gateway/test_qqbot.py b/tests/gateway/test_qqbot.py index 7ea3ceb143..5473c7a4b2 100644 --- a/tests/gateway/test_qqbot.py +++ b/tests/gateway/test_qqbot.py @@ -298,7 +298,7 @@ class TestDetectMessageType: return QQAdapter._detect_message_type(media_urls, media_types) def test_no_media(self): - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType assert self._fn([], []) == MessageType.TEXT diff --git a/tests/gateway/test_queue_command.py b/tests/gateway/test_queue_command.py index d4b693333d..0bd332a78a 100644 --- a/tests/gateway/test_queue_command.py +++ b/tests/gateway/test_queue_command.py @@ -16,7 +16,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_queue_consumption.py b/tests/gateway/test_queue_consumption.py index ad258b0023..aff487ac62 100644 --- a/tests/gateway/test_queue_consumption.py +++ b/tests/gateway/test_queue_consumption.py @@ -12,11 +12,10 @@ from unittest.mock import MagicMock from gateway.run import _dequeue_pending_event from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, PlatformConfig, Platform, ) +from gateway.platforms.event import MessageEvent, MessageType # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_queued_native_image_session_key.py b/tests/gateway/test_queued_native_image_session_key.py index e248975615..beb0b7626d 100644 --- a/tests/gateway/test_queued_native_image_session_key.py +++ b/tests/gateway/test_queued_native_image_session_key.py @@ -7,7 +7,8 @@ from types import SimpleNamespace import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource diff --git a/tests/gateway/test_reaped_session_recovery.py b/tests/gateway/test_reaped_session_recovery.py index 15983d1853..2937d8ca84 100644 --- a/tests/gateway/test_reaped_session_recovery.py +++ b/tests/gateway/test_reaped_session_recovery.py @@ -21,7 +21,7 @@ from gateway.config import ( Platform, PlatformConfig, ) -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource, SessionStore diff --git a/tests/gateway/test_reasoning_command.py b/tests/gateway/test_reasoning_command.py index 128e9c301b..de83c96566 100644 --- a/tests/gateway/test_reasoning_command.py +++ b/tests/gateway/test_reasoning_command.py @@ -11,7 +11,7 @@ import yaml import gateway.run as gateway_run from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_reload_skills_command.py b/tests/gateway/test_reload_skills_command.py index d6a27d4550..3c25b3b27a 100644 --- a/tests/gateway/test_reload_skills_command.py +++ b/tests/gateway/test_reload_skills_command.py @@ -20,7 +20,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_reply_to_injection.py b/tests/gateway/test_reply_to_injection.py index bc6f9fe7ab..c260b2274a 100644 --- a/tests/gateway/test_reply_to_injection.py +++ b/tests/gateway/test_reply_to_injection.py @@ -10,7 +10,7 @@ which prior message the user is referencing. import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_restart_drain.py b/tests/gateway/test_restart_drain.py index 0d643e6571..765badb4b9 100644 --- a/tests/gateway/test_restart_drain.py +++ b/tests/gateway/test_restart_drain.py @@ -8,7 +8,7 @@ import pytest import gateway.run as gateway_run from agent.i18n import t -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.restart import ( DEFAULT_GATEWAY_RESTART_DRAIN_TIMEOUT, DEFAULT_GATEWAY_SIGNAL_INTERRUPT_GRACE_TIMEOUT, diff --git a/tests/gateway/test_restart_notification.py b/tests/gateway/test_restart_notification.py index b1efc54f18..e3fd769398 100644 --- a/tests/gateway/test_restart_notification.py +++ b/tests/gateway/test_restart_notification.py @@ -8,7 +8,8 @@ import pytest import gateway.run as gateway_run from gateway.config import HomeChannel, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, SendResult +from gateway.platforms.base import SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import build_session_key from tests.gateway.restart_test_helpers import ( make_restart_runner, diff --git a/tests/gateway/test_restart_redelivery_dedup.py b/tests/gateway/test_restart_redelivery_dedup.py index 6b5d899ef5..af4f3be040 100644 --- a/tests/gateway/test_restart_redelivery_dedup.py +++ b/tests/gateway/test_restart_redelivery_dedup.py @@ -12,7 +12,7 @@ from unittest.mock import MagicMock import pytest import gateway.run as gateway_run -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from tests.gateway.restart_test_helpers import make_restart_runner, make_restart_source diff --git a/tests/gateway/test_restart_resume_pending.py b/tests/gateway/test_restart_resume_pending.py index fe147ae576..89ee4705cd 100644 --- a/tests/gateway/test_restart_resume_pending.py +++ b/tests/gateway/test_restart_resume_pending.py @@ -33,7 +33,8 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import GatewayConfig, HomeChannel, Platform -from gateway.platforms.base import MessageEvent, MessageType, SendResult +from gateway.platforms.base import SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import ( _AGENT_PENDING_SENTINEL, _auto_continue_freshness_window, diff --git a/tests/gateway/test_restart_service_detection.py b/tests/gateway/test_restart_service_detection.py index 65baef8b2a..aeb1611cf5 100644 --- a/tests/gateway/test_restart_service_detection.py +++ b/tests/gateway/test_restart_service_detection.py @@ -19,7 +19,7 @@ from unittest.mock import MagicMock import pytest import gateway.run as gateway_run -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.restart import EXTERNAL_GATEWAY_SUPERVISOR_ENV from tests.gateway.restart_test_helpers import make_restart_runner, make_restart_source diff --git a/tests/gateway/test_resume_command.py b/tests/gateway/test_resume_command.py index 74172b5561..e1bf10ebb2 100644 --- a/tests/gateway/test_resume_command.py +++ b/tests/gateway/test_resume_command.py @@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_retry_replacement.py b/tests/gateway/test_retry_replacement.py index 4dec6eba04..ed3f35f32f 100644 --- a/tests/gateway/test_retry_replacement.py +++ b/tests/gateway/test_retry_replacement.py @@ -13,7 +13,7 @@ from agent.context_compressor import ( _SUMMARY_END_MARKER, ) from gateway.config import GatewayConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionStore diff --git a/tests/gateway/test_retry_response.py b/tests/gateway/test_retry_response.py index e1bcf7770d..c8314622a6 100644 --- a/tests/gateway/test_retry_response.py +++ b/tests/gateway/test_retry_response.py @@ -7,7 +7,7 @@ so users never received the final response. import pytest from unittest.mock import AsyncMock, MagicMock from gateway.run import GatewayRunner -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType @pytest.fixture diff --git a/tests/gateway/test_run_progress_topics.py b/tests/gateway/test_run_progress_topics.py index 583c48d52d..9d2fadd00b 100644 --- a/tests/gateway/test_run_progress_topics.py +++ b/tests/gateway/test_run_progress_topics.py @@ -11,7 +11,8 @@ import pytest import gateway.platforms.base as base_platform from gateway.config import Platform, PlatformConfig, StreamingConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource diff --git a/tests/gateway/test_runner_fatal_adapter.py b/tests/gateway/test_runner_fatal_adapter.py index d50a3058f4..9e1382af66 100644 --- a/tests/gateway/test_runner_fatal_adapter.py +++ b/tests/gateway/test_runner_fatal_adapter.py @@ -4,7 +4,8 @@ from unittest.mock import AsyncMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent from gateway.run import GatewayRunner from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_running_agent_session_toggles.py b/tests/gateway/test_running_agent_session_toggles.py index 09663b1bab..d82e384d9e 100644 --- a/tests/gateway/test_running_agent_session_toggles.py +++ b/tests/gateway/test_running_agent_session_toggles.py @@ -26,7 +26,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_send_voice_reply_notify.py b/tests/gateway/test_send_voice_reply_notify.py index 060c826fc5..905c4d40aa 100644 --- a/tests/gateway/test_send_voice_reply_notify.py +++ b/tests/gateway/test_send_voice_reply_notify.py @@ -16,7 +16,7 @@ from unittest.mock import AsyncMock import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_session.py b/tests/gateway/test_session.py index 348ee5ee9b..43e31c14d1 100644 --- a/tests/gateway/test_session.py +++ b/tests/gateway/test_session.py @@ -7,7 +7,7 @@ from pathlib import Path from unittest.mock import patch, MagicMock from hermes_state import SessionDB from gateway.config import Platform, HomeChannel, GatewayConfig, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import ( SessionEntry, SessionSource, diff --git a/tests/gateway/test_session_boundary_security_state.py b/tests/gateway/test_session_boundary_security_state.py index 0db26f46d6..e1cf181e02 100644 --- a/tests/gateway/test_session_boundary_security_state.py +++ b/tests/gateway/test_session_boundary_security_state.py @@ -7,7 +7,7 @@ from unittest.mock import MagicMock import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key from tools import approval as approval_mod from tools import slash_confirm as slash_confirm_mod diff --git a/tests/gateway/test_session_hygiene.py b/tests/gateway/test_session_hygiene.py index 1bb266b05b..8128e5c56a 100644 --- a/tests/gateway/test_session_hygiene.py +++ b/tests/gateway/test_session_hygiene.py @@ -22,7 +22,8 @@ import pytest from agent.model_metadata import estimate_messages_tokens_rough from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource diff --git a/tests/gateway/test_session_hygiene_turnhold_adoption.py b/tests/gateway/test_session_hygiene_turnhold_adoption.py index 1b6c209cbd..752ecfd7bf 100644 --- a/tests/gateway/test_session_hygiene_turnhold_adoption.py +++ b/tests/gateway/test_session_hygiene_turnhold_adoption.py @@ -31,7 +31,8 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource diff --git a/tests/gateway/test_session_model_reset.py b/tests/gateway/test_session_model_reset.py index 5c0ca5acbd..40c2903bd8 100644 --- a/tests/gateway/test_session_model_reset.py +++ b/tests/gateway/test_session_model_reset.py @@ -6,7 +6,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_session_race_guard.py b/tests/gateway/test_session_race_guard.py index 8797bcada2..b7961c900d 100644 --- a/tests/gateway/test_session_race_guard.py +++ b/tests/gateway/test_session_race_guard.py @@ -14,7 +14,8 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, merge_pending_message_event +from gateway.platforms.base import merge_pending_message_event +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner, _AGENT_PENDING_SENTINEL from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_session_split_brain_11016.py b/tests/gateway/test_session_split_brain_11016.py index b6a850244e..31b63a8da5 100644 --- a/tests/gateway/test_session_split_brain_11016.py +++ b/tests/gateway/test_session_split_brain_11016.py @@ -24,9 +24,8 @@ import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_shared_group_sender_prefix.py b/tests/gateway/test_shared_group_sender_prefix.py index aebf9fa990..84b3139510 100644 --- a/tests/gateway/test_shared_group_sender_prefix.py +++ b/tests/gateway/test_shared_group_sender_prefix.py @@ -1,7 +1,7 @@ import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_signal.py b/tests/gateway/test_signal.py index fb668dc34d..3cfe69ba1f 100644 --- a/tests/gateway/test_signal.py +++ b/tests/gateway/test_signal.py @@ -596,7 +596,7 @@ class TestSignalInboundMessageTypeClassification: @pytest.mark.asyncio async def test_pdf_attachment_sets_document_type(self, monkeypatch): """A PDF attachment (application/pdf) must produce MessageType.DOCUMENT, not TEXT.""" - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType event = await self._dispatch_single_attachment( monkeypatch, @@ -615,7 +615,7 @@ class TestSignalInboundMessageTypeClassification: @pytest.mark.asyncio async def test_text_plain_attachment_sets_document_type(self, monkeypatch): """A text/plain attachment must produce MessageType.DOCUMENT, not TEXT.""" - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType event = await self._dispatch_single_attachment( monkeypatch, diff --git a/tests/gateway/test_slack.py b/tests/gateway/test_slack.py index 395a885d6f..158c20275a 100644 --- a/tests/gateway/test_slack.py +++ b/tests/gateway/test_slack.py @@ -25,13 +25,12 @@ import agent.secret_scope as secret_scope from gateway.config import GatewayConfig, Platform, PlatformConfig from gateway.run import GatewayRunner from gateway.platforms.base import ( - MessageEvent, - MessageType, SendResult, SUPPORTED_VIDEO_TYPES, SendResult, is_host_excluded_by_no_proxy, ) +from gateway.platforms.event import MessageEvent, MessageType # --------------------------------------------------------------------------- @@ -2903,7 +2902,8 @@ class TestReactions: assert "1234567890.000001" in adapter._reacting_message_ids # Simulate the base class calling on_processing_start - from gateway.platforms.base import MessageEvent, MessageType, SessionSource + from gateway.platforms.base import SessionSource + from gateway.platforms.event import MessageEvent, MessageType from gateway.config import Platform source = SessionSource( @@ -2925,7 +2925,7 @@ class TestReactions: assert add_calls[0].kwargs["name"] == "eyes" # Simulate the base class calling on_processing_complete - from gateway.platforms.base import ProcessingOutcome + from gateway.platforms.event import ProcessingOutcome await adapter.on_processing_complete(msg_event, ProcessingOutcome.SUCCESS) diff --git a/tests/gateway/test_slack_channel_skills.py b/tests/gateway/test_slack_channel_skills.py index cdc35d5297..1c715a2dcd 100644 --- a/tests/gateway/test_slack_channel_skills.py +++ b/tests/gateway/test_slack_channel_skills.py @@ -59,7 +59,8 @@ class TestSlackMessageEventAutoSkill: def test_message_event_carries_auto_skill(self): """Simulate the handler wiring: resolve + attach to MessageEvent.""" - from gateway.platforms.base import MessageEvent, MessageType, Platform, SessionSource, resolve_channel_skills + from gateway.platforms.base import Platform, SessionSource, resolve_channel_skills + from gateway.platforms.event import MessageEvent, MessageType config_extra = { "channel_skill_bindings": [ diff --git a/tests/gateway/test_slack_relay_parent_command.py b/tests/gateway/test_slack_relay_parent_command.py index c676ebe91f..4a9eef61e4 100644 --- a/tests/gateway/test_slack_relay_parent_command.py +++ b/tests/gateway/test_slack_relay_parent_command.py @@ -1,7 +1,7 @@ import pytest from gateway.config import Platform -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType from gateway.relay.ws_transport import _event_from_wire diff --git a/tests/gateway/test_slack_runner_ignored_channels.py b/tests/gateway/test_slack_runner_ignored_channels.py index e4c0547ff0..d94a8ca80b 100644 --- a/tests/gateway/test_slack_runner_ignored_channels.py +++ b/tests/gateway/test_slack_runner_ignored_channels.py @@ -2,7 +2,8 @@ import pytest from unittest.mock import AsyncMock from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, SendResult +from gateway.platforms.base import SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import ( GatewayRunner, _is_slack_ignored_channel, diff --git a/tests/gateway/test_slash_access_dispatch.py b/tests/gateway/test_slash_access_dispatch.py index 2b765f004d..ef323f12b8 100644 --- a/tests/gateway/test_slash_access_dispatch.py +++ b/tests/gateway/test_slash_access_dispatch.py @@ -25,7 +25,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_stacked_skill_platform_disabled.py b/tests/gateway/test_stacked_skill_platform_disabled.py index 21ed2a8d27..9aa8a0f5c0 100644 --- a/tests/gateway/test_stacked_skill_platform_disabled.py +++ b/tests/gateway/test_stacked_skill_platform_disabled.py @@ -19,7 +19,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_status_command.py b/tests/gateway/test_status_command.py index ec179816c7..f06ffd4cc3 100644 --- a/tests/gateway/test_status_command.py +++ b/tests/gateway/test_status_command.py @@ -9,7 +9,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key @@ -376,7 +376,8 @@ async def test_status_command_bypasses_active_session_guard(): """When an agent is running, /status must be dispatched immediately via base.handle_message — not queued or treated as an interrupt (#5046).""" import asyncio - from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType + from gateway.platforms.base import BasePlatformAdapter + from gateway.platforms.event import MessageEvent, MessageType from gateway.session import build_session_key from gateway.config import Platform, PlatformConfig diff --git a/tests/gateway/test_steer_command.py b/tests/gateway/test_steer_command.py index 889fd73bf0..63e21432f1 100644 --- a/tests/gateway/test_steer_command.py +++ b/tests/gateway/test_steer_command.py @@ -20,7 +20,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_steer_fifo_overwrite.py b/tests/gateway/test_steer_fifo_overwrite.py index e3bffe5cb8..522211784a 100644 --- a/tests/gateway/test_steer_fifo_overwrite.py +++ b/tests/gateway/test_steer_fifo_overwrite.py @@ -25,7 +25,7 @@ from unittest.mock import MagicMock def _prequeue(runner, adapter, sk): """Pre-stage Q1 in the pending slot and Q2 in the overflow tail.""" - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType # Ensure _queued_events is initialized (mirrors GatewayRunner.__init__) if not hasattr(runner, "_queued_events"): diff --git a/tests/gateway/test_stop_thread_sibling.py b/tests/gateway/test_stop_thread_sibling.py index 9666160a9b..63fe48708e 100644 --- a/tests/gateway/test_stop_thread_sibling.py +++ b/tests/gateway/test_stop_thread_sibling.py @@ -12,7 +12,8 @@ import pytest from gateway.run import GatewayRunner, _AGENT_PENDING_SENTINEL, _INTERRUPT_REASON_STOP from gateway.session import SessionSource, build_session_key -from gateway.platforms.base import Platform, MessageEvent, MessageType +from gateway.platforms.base import Platform +from gateway.platforms.event import MessageEvent, MessageType class _FakeAgent: diff --git a/tests/gateway/test_streaming_tts_gateway_regression.py b/tests/gateway/test_streaming_tts_gateway_regression.py index 4979f773c3..13729e4e20 100644 --- a/tests/gateway/test_streaming_tts_gateway_regression.py +++ b/tests/gateway/test_streaming_tts_gateway_regression.py @@ -24,7 +24,7 @@ import pytest import gateway.run as gateway_run from gateway.config import Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource diff --git a/tests/gateway/test_stt_config.py b/tests/gateway/test_stt_config.py index d8245dec14..4f72c58c4d 100644 --- a/tests/gateway/test_stt_config.py +++ b/tests/gateway/test_stt_config.py @@ -7,7 +7,7 @@ import pytest import yaml from gateway.config import GatewayConfig, Platform, load_gateway_config -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource diff --git a/tests/gateway/test_subagent_protection_30170.py b/tests/gateway/test_subagent_protection_30170.py index d71a1dd043..eda68f4de2 100644 --- a/tests/gateway/test_subagent_protection_30170.py +++ b/tests/gateway/test_subagent_protection_30170.py @@ -48,12 +48,11 @@ sys.modules.setdefault("telegram", _tg) sys.modules.setdefault("telegram.constants", _tg.constants) sys.modules.setdefault("telegram.ext", types.ModuleType("telegram.ext")) -from gateway.platforms.base import ( # noqa: E402 - MessageEvent, - MessageType, +from gateway.platforms.base import ( SessionSource, build_session_key, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner, _AGENT_PENDING_SENTINEL # noqa: E402 diff --git a/tests/gateway/test_teams.py b/tests/gateway/test_teams.py index 160e48e40b..6f133e0439 100644 --- a/tests/gateway/test_teams.py +++ b/tests/gateway/test_teams.py @@ -592,7 +592,7 @@ class TestTeamsAttachmentClassification: @pytest.mark.anyio async def test_file_download_info_sets_document_type(self): - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType adapter = self._make_adapter() adapter._fetch_attachment_bytes = AsyncMock(return_value=b"%PDF-1.4 fake") @@ -610,7 +610,7 @@ class TestTeamsAttachmentClassification: @pytest.mark.anyio async def test_mixed_image_and_document_prefers_document(self): - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType adapter = self._make_adapter() adapter._fetch_attachment_bytes = AsyncMock(return_value=b"%PDF-1.4 fake") diff --git a/tests/gateway/test_telegram_audio_vs_voice.py b/tests/gateway/test_telegram_audio_vs_voice.py index b9e54c5935..7b351a1e4d 100644 --- a/tests/gateway/test_telegram_audio_vs_voice.py +++ b/tests/gateway/test_telegram_audio_vs_voice.py @@ -17,7 +17,7 @@ from unittest.mock import patch import pytest from gateway.config import GatewayConfig, Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource from typing import TYPE_CHECKING diff --git a/tests/gateway/test_telegram_auth_check.py b/tests/gateway/test_telegram_auth_check.py index 293d437a59..627cfdbb0d 100644 --- a/tests/gateway/test_telegram_auth_check.py +++ b/tests/gateway/test_telegram_auth_check.py @@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, patch import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType def _make_adapter(allow_from=None, allowed_chats=None, group_allowed_chats=None, callback_auth=None, **extra_overrides): diff --git a/tests/gateway/test_telegram_bot_auth_bypass.py b/tests/gateway/test_telegram_bot_auth_bypass.py index 6f3795be04..c46d7e4d9f 100644 --- a/tests/gateway/test_telegram_bot_auth_bypass.py +++ b/tests/gateway/test_telegram_bot_auth_bypass.py @@ -97,7 +97,7 @@ def _build_telegram_message(*, is_bot: bool): def _capture_build_source_is_bot(is_bot: bool): - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType from plugins.platforms.telegram.adapter import TelegramAdapter adapter = object.__new__(TelegramAdapter) diff --git a/tests/gateway/test_telegram_channel_posts.py b/tests/gateway/test_telegram_channel_posts.py index 6fe8bec97c..fb078f628d 100644 --- a/tests/gateway/test_telegram_channel_posts.py +++ b/tests/gateway/test_telegram_channel_posts.py @@ -16,7 +16,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import PlatformConfig -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType def _build_telegram_stubs(): diff --git a/tests/gateway/test_telegram_documents.py b/tests/gateway/test_telegram_documents.py index fd3b406a08..ef29f11303 100644 --- a/tests/gateway/test_telegram_documents.py +++ b/tests/gateway/test_telegram_documents.py @@ -17,11 +17,10 @@ import pytest from gateway.config import PlatformConfig from gateway.platforms.base import ( - MessageEvent, - MessageType, SendResult, SUPPORTED_VIDEO_TYPES, ) +from gateway.platforms.event import MessageEvent, MessageType # --------------------------------------------------------------------------- diff --git a/tests/gateway/test_telegram_group_gating.py b/tests/gateway/test_telegram_group_gating.py index e39920ccaf..73c932b929 100644 --- a/tests/gateway/test_telegram_group_gating.py +++ b/tests/gateway/test_telegram_group_gating.py @@ -4,7 +4,7 @@ from types import SimpleNamespace from unittest.mock import AsyncMock, Mock from gateway.config import Platform, PlatformConfig, load_gateway_config -from gateway.platforms.base import MessageType +from gateway.platforms.event import MessageType from gateway.session import SessionSource @@ -223,7 +223,8 @@ def test_observed_group_context_uses_shared_source_and_prompt_for_later_mentions def test_observed_group_context_preserves_slash_command_text_for_dispatch(): - from gateway.platforms.base import MessageEvent, MessageType, Platform, SessionSource + from gateway.platforms.base import Platform, SessionSource + from gateway.platforms.event import MessageEvent, MessageType adapter = _make_adapter( require_mention=True, diff --git a/tests/gateway/test_telegram_photo_interrupts.py b/tests/gateway/test_telegram_photo_interrupts.py index 74fb8baa3e..18a4972cca 100644 --- a/tests/gateway/test_telegram_photo_interrupts.py +++ b/tests/gateway/test_telegram_photo_interrupts.py @@ -3,7 +3,7 @@ from unittest.mock import MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key from gateway.run import GatewayRunner diff --git a/tests/gateway/test_telegram_reactions.py b/tests/gateway/test_telegram_reactions.py index 69dc8103e0..4c2377db37 100644 --- a/tests/gateway/test_telegram_reactions.py +++ b/tests/gateway/test_telegram_reactions.py @@ -6,7 +6,7 @@ from unittest.mock import AsyncMock import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, ProcessingOutcome +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from gateway.session import SessionSource diff --git a/tests/gateway/test_telegram_reply_quote.py b/tests/gateway/test_telegram_reply_quote.py index 7150ed1dc8..be10e3e61a 100644 --- a/tests/gateway/test_telegram_reply_quote.py +++ b/tests/gateway/test_telegram_reply_quote.py @@ -55,7 +55,7 @@ def _make_message( def test_native_partial_quote_used_as_reply_to_text(): """When ``message.quote`` is present, prefer the selected substring.""" - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType adapter = _make_adapter() msg = _make_message( diff --git a/tests/gateway/test_telegram_rich_messages.py b/tests/gateway/test_telegram_rich_messages.py index 932bce1827..522591ecb1 100644 --- a/tests/gateway/test_telegram_rich_messages.py +++ b/tests/gateway/test_telegram_rich_messages.py @@ -808,7 +808,7 @@ def _reply_message_with_rich_blocks( async def test_rich_reply_records_and_recovers_text(monkeypatch, tmp_path): """A reply to a rich-sent message resolves the original text via the index.""" monkeypatch.setenv("HERMES_HOME", str(tmp_path)) - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType from gateway import rich_sent_store adapter = _make_adapter() diff --git a/tests/gateway/test_telegram_text_batching.py b/tests/gateway/test_telegram_text_batching.py index e3e07090a6..d2cfa21abd 100644 --- a/tests/gateway/test_telegram_text_batching.py +++ b/tests/gateway/test_telegram_text_batching.py @@ -12,7 +12,8 @@ from unittest.mock import AsyncMock, patch import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, SessionSource +from gateway.platforms.base import SessionSource +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import build_session_key diff --git a/tests/gateway/test_telegram_thread_fallback.py b/tests/gateway/test_telegram_thread_fallback.py index 046479c2a7..cba9f9a86f 100644 --- a/tests/gateway/test_telegram_thread_fallback.py +++ b/tests/gateway/test_telegram_thread_fallback.py @@ -18,12 +18,11 @@ import pytest from gateway.config import PlatformConfig, Platform from gateway.platforms.base import ( - MessageEvent, - MessageType, SendResult, _reply_anchor_for_event, _thread_metadata_for_source, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import build_session_key diff --git a/tests/gateway/test_telegram_topic_mode.py b/tests/gateway/test_telegram_topic_mode.py index 2a85a82443..a3ce15b32f 100644 --- a/tests/gateway/test_telegram_topic_mode.py +++ b/tests/gateway/test_telegram_topic_mode.py @@ -19,7 +19,7 @@ from agent.context_compressor import ( ) from hermes_state import SessionDB from gateway.config import GatewayConfig, HomeChannel, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_telegram_voice_v0_regressions.py b/tests/gateway/test_telegram_voice_v0_regressions.py index 05c2fbcffe..9bad21eda0 100644 --- a/tests/gateway/test_telegram_voice_v0_regressions.py +++ b/tests/gateway/test_telegram_voice_v0_regressions.py @@ -14,7 +14,8 @@ if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from plugins.platforms.telegram.adapter import TelegramAdapter from gateway.run import GatewayRunner from gateway.session import SessionSource diff --git a/tests/gateway/test_text_batching.py b/tests/gateway/test_text_batching.py index e55108da02..63504c0b74 100644 --- a/tests/gateway/test_text_batching.py +++ b/tests/gateway/test_text_batching.py @@ -14,7 +14,8 @@ from unittest.mock import AsyncMock import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, SessionSource +from gateway.platforms.base import SessionSource +from gateway.platforms.event import MessageEvent, MessageType # ===================================================================== diff --git a/tests/gateway/test_title_command.py b/tests/gateway/test_title_command.py index e108251819..71aac29490 100644 --- a/tests/gateway/test_title_command.py +++ b/tests/gateway/test_title_command.py @@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_tool_response_drop_recovery.py b/tests/gateway/test_tool_response_drop_recovery.py index 3c59d8eb7e..885b24d316 100644 --- a/tests/gateway/test_tool_response_drop_recovery.py +++ b/tests/gateway/test_tool_response_drop_recovery.py @@ -27,9 +27,9 @@ import pytest from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, SendResult, ) +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_tts_media_routing.py b/tests/gateway/test_tts_media_routing.py index fd3ed9ee44..5f3d587d92 100644 --- a/tests/gateway/test_tts_media_routing.py +++ b/tests/gateway/test_tts_media_routing.py @@ -16,7 +16,8 @@ from unittest.mock import AsyncMock import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import BasePlatformAdapter, MessageEvent, MessageType, SendResult +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.run import GatewayRunner from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_typing_indicator_toggle.py b/tests/gateway/test_typing_indicator_toggle.py index a29ebec41f..e853854922 100644 --- a/tests/gateway/test_typing_indicator_toggle.py +++ b/tests/gateway/test_typing_indicator_toggle.py @@ -18,9 +18,8 @@ import pytest from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, - MessageEvent, - MessageType, ) +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource, build_session_key diff --git a/tests/gateway/test_unauthorized_dm_behavior.py b/tests/gateway/test_unauthorized_dm_behavior.py index c0bd88879d..4ea8cbc416 100644 --- a/tests/gateway/test_unauthorized_dm_behavior.py +++ b/tests/gateway/test_unauthorized_dm_behavior.py @@ -4,7 +4,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_unknown_command.py b/tests/gateway/test_unknown_command.py index bffcde9e7b..abe23da48c 100644 --- a/tests/gateway/test_unknown_command.py +++ b/tests/gateway/test_unknown_command.py @@ -12,7 +12,7 @@ from unittest.mock import AsyncMock, MagicMock import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionEntry, SessionSource, build_session_key diff --git a/tests/gateway/test_update_command.py b/tests/gateway/test_update_command.py index 69916e9229..58898b9322 100644 --- a/tests/gateway/test_update_command.py +++ b/tests/gateway/test_update_command.py @@ -11,7 +11,7 @@ from unittest.mock import patch, MagicMock, AsyncMock import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_update_streaming.py b/tests/gateway/test_update_streaming.py index 8c58113bc6..8e213f8aa2 100644 --- a/tests/gateway/test_update_streaming.py +++ b/tests/gateway/test_update_streaming.py @@ -16,7 +16,7 @@ from unittest.mock import patch, MagicMock, AsyncMock import pytest from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_verbose_command.py b/tests/gateway/test_verbose_command.py index 5528c5d89a..d9cc47969a 100644 --- a/tests/gateway/test_verbose_command.py +++ b/tests/gateway/test_verbose_command.py @@ -7,7 +7,7 @@ import yaml import gateway.run as gateway_run from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource diff --git a/tests/gateway/test_video_context_note.py b/tests/gateway/test_video_context_note.py index f0cd84575c..69dc17d7a9 100644 --- a/tests/gateway/test_video_context_note.py +++ b/tests/gateway/test_video_context_note.py @@ -5,7 +5,7 @@ from unittest.mock import patch import pytest from gateway.config import GatewayConfig, Platform -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.session import SessionSource from typing import TYPE_CHECKING diff --git a/tests/gateway/test_voice_command.py b/tests/gateway/test_voice_command.py index beb06d35e8..12856f8c01 100644 --- a/tests/gateway/test_voice_command.py +++ b/tests/gateway/test_voice_command.py @@ -52,7 +52,8 @@ def _ensure_discord_mock(): _ensure_discord_mock() -from gateway.platforms.base import MessageEvent, MessageType, SessionSource +from gateway.platforms.base import SessionSource +from gateway.platforms.event import MessageEvent, MessageType # --------------------------------------------------------------------------- @@ -1755,7 +1756,8 @@ class TestVoiceTTSPlayback: def _call_should_reply(self, runner, voice_mode, msg_type, response="Hello", agent_msgs=None, already_sent=False): - from gateway.platforms.base import MessageEvent, SessionSource + from gateway.platforms.base import SessionSource + from gateway.platforms.event import MessageEvent from gateway.config import Platform runner._voice_mode["discord:ch1"] = voice_mode source = SessionSource( @@ -1771,20 +1773,20 @@ class TestVoiceTTSPlayback: def test_voice_input_runner_skips(self): """Streaming OFF + voice input: runner skips — base adapter handles.""" - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType runner = self._make_runner() assert self._call_should_reply(runner, "all", MessageType.VOICE, already_sent=False) is False def test_text_input_voice_all_runner_fires(self): """Streaming OFF + text input + voice_mode=all: runner generates TTS.""" - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType runner = self._make_runner() assert self._call_should_reply(runner, "all", MessageType.TEXT, already_sent=False) is True def test_error_response_no_tts(self): """Error response: no TTS regardless of voice_mode.""" - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType runner = self._make_runner() assert self._call_should_reply(runner, "all", MessageType.TEXT, response="Error: boom") is False @@ -1794,7 +1796,7 @@ class TestVoiceTTSPlayback: def test_streaming_on_agent_tts_dedup(self): """Streaming ON + agent called TTS: runner skips (dedup still works).""" - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType runner = self._make_runner() agent_msgs = [{"role": "assistant", "tool_calls": [ {"id": "1", "type": "function", "function": {"name": "text_to_speech", "arguments": "{}"}} diff --git a/tests/gateway/test_voice_mode_platform_isolation.py b/tests/gateway/test_voice_mode_platform_isolation.py index f6c5932f8b..5444b610cd 100644 --- a/tests/gateway/test_voice_mode_platform_isolation.py +++ b/tests/gateway/test_voice_mode_platform_isolation.py @@ -145,7 +145,8 @@ class TestVoiceModeProfileIsolation: async def test_voice_state_and_transcripts_stay_with_the_owning_bot(self, tmp_path): from types import SimpleNamespace - from gateway.platforms.base import MessageEvent, MessageType, SessionSource + from gateway.platforms.base import SessionSource + from gateway.platforms.event import MessageEvent, MessageType runner = _make_runner() runner._VOICE_MODE_PATH = tmp_path / "voice.json" diff --git a/tests/gateway/test_webhook_deliver_only.py b/tests/gateway/test_webhook_deliver_only.py index 1eac651505..0bd5a190d0 100644 --- a/tests/gateway/test_webhook_deliver_only.py +++ b/tests/gateway/test_webhook_deliver_only.py @@ -22,7 +22,8 @@ from aiohttp import web from aiohttp.test_utils import TestClient, TestServer from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, SendResult +from gateway.platforms.base import SendResult +from gateway.platforms.event import MessageEvent from gateway.platforms.webhook import WebhookAdapter, _INSECURE_NO_AUTH diff --git a/tests/gateway/test_webhook_integration.py b/tests/gateway/test_webhook_integration.py index dea960bba1..2fae386b6a 100644 --- a/tests/gateway/test_webhook_integration.py +++ b/tests/gateway/test_webhook_integration.py @@ -22,7 +22,8 @@ from gateway.config import ( Platform, PlatformConfig, ) -from gateway.platforms.base import MessageEvent, SendResult +from gateway.platforms.base import SendResult +from gateway.platforms.event import MessageEvent from gateway.platforms.webhook import WebhookAdapter, _INSECURE_NO_AUTH diff --git a/tests/gateway/test_webhook_session_close.py b/tests/gateway/test_webhook_session_close.py index 9ea0adf435..9901a1bb74 100644 --- a/tests/gateway/test_webhook_session_close.py +++ b/tests/gateway/test_webhook_session_close.py @@ -27,7 +27,7 @@ import asyncio import pytest from gateway.config import GatewayConfig, Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.platforms.webhook import WebhookAdapter, _INSECURE_NO_AUTH from gateway.session import SessionSource, SessionStore diff --git a/tests/gateway/test_wecom.py b/tests/gateway/test_wecom.py index 622da346a1..fe62c65a5e 100644 --- a/tests/gateway/test_wecom.py +++ b/tests/gateway/test_wecom.py @@ -654,7 +654,7 @@ class TestTextBatchFlushRace: async def test_superseded_task_does_not_pop_or_process_event(self): """A flush task that has been superseded must leave the event in the batch dict for the new task to handle.""" - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from plugins.platforms.wecom.adapter import WeComAdapter adapter = WeComAdapter(PlatformConfig(enabled=True)) @@ -697,7 +697,7 @@ class TestTextBatchFlushRace: @pytest.mark.asyncio async def test_active_task_processes_event_normally(self): """When the task is not superseded it must still process the event.""" - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType from plugins.platforms.wecom.adapter import WeComAdapter adapter = WeComAdapter(PlatformConfig(enabled=True)) @@ -811,7 +811,7 @@ class TestAttachmentTextMerge: await asyncio.sleep(0.3) adapter.handle_message.assert_awaited_once() event = adapter.handle_message.await_args.args[0] - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType assert event.text == "what is this?" assert event.media_urls == ["/tmp/x.png"] @@ -831,7 +831,7 @@ class TestAttachmentTextMerge: await asyncio.sleep(0.3) adapter.handle_message.assert_awaited_once() event = adapter.handle_message.await_args.args[0] - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType assert event.media_urls == ["/tmp/x.png"] assert event.message_type == MessageType.PHOTO @@ -880,7 +880,7 @@ class TestAttachmentTextMerge: await asyncio.sleep(0.2) adapter.handle_message.assert_awaited_once() event = adapter.handle_message.await_args.args[0] - from gateway.platforms.base import MessageType + from gateway.platforms.event import MessageType assert event.text == "just text" assert event.media_urls == [] diff --git a/tests/gateway/test_weixin.py b/tests/gateway/test_weixin.py index 52a6e82f69..0862fa1dea 100644 --- a/tests/gateway/test_weixin.py +++ b/tests/gateway/test_weixin.py @@ -11,7 +11,7 @@ import pytest from gateway.config import PlatformConfig from gateway.config import GatewayConfig, HomeChannel, Platform, _apply_env_overrides from gateway.platforms.base import SendResult -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from gateway.platforms import weixin from gateway.platforms.weixin import ContextTokenStore, WeixinAdapter from tools.send_message_tool import _send_to_platform diff --git a/tests/gateway/test_whatsapp_reply_prefix.py b/tests/gateway/test_whatsapp_reply_prefix.py index 4703a8a4ae..26a008c2b0 100644 --- a/tests/gateway/test_whatsapp_reply_prefix.py +++ b/tests/gateway/test_whatsapp_reply_prefix.py @@ -16,7 +16,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType class _AsyncResponseContext: diff --git a/tests/gateway/test_whatsapp_text_batching.py b/tests/gateway/test_whatsapp_text_batching.py index 72feecbb42..2fb6c613fc 100644 --- a/tests/gateway/test_whatsapp_text_batching.py +++ b/tests/gateway/test_whatsapp_text_batching.py @@ -11,7 +11,7 @@ Batch delays are read from ``config.extra`` (config.yaml), not env vars. import asyncio from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from plugins.platforms.whatsapp.adapter import WhatsAppAdapter from gateway.session import SessionSource diff --git a/tests/gateway/test_yolo_command.py b/tests/gateway/test_yolo_command.py index 46afd68adc..501b1ec625 100644 --- a/tests/gateway/test_yolo_command.py +++ b/tests/gateway/test_yolo_command.py @@ -6,7 +6,7 @@ import pytest import gateway.run as gateway_run from gateway.config import Platform -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from gateway.session import SessionSource from tools.approval import disable_session_yolo, is_session_yolo_enabled diff --git a/tests/hermes_cli/test_pre_command_hook.py b/tests/hermes_cli/test_pre_command_hook.py index 47b7136311..c3a4079f5d 100644 --- a/tests/hermes_cli/test_pre_command_hook.py +++ b/tests/hermes_cli/test_pre_command_hook.py @@ -199,7 +199,7 @@ def _make_source(): def _make_event(text: str): - from gateway.platforms.base import MessageEvent, MessageType + from gateway.platforms.event import MessageEvent, MessageType return MessageEvent( text=text, diff --git a/tests/plugins/platforms/photon/test_inbound.py b/tests/plugins/platforms/photon/test_inbound.py index 8987a8b428..5e32d776d3 100644 --- a/tests/plugins/platforms/photon/test_inbound.py +++ b/tests/plugins/platforms/photon/test_inbound.py @@ -15,7 +15,7 @@ from typing import Any, Dict, List import pytest from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from plugins.platforms.photon.adapter import PhotonAdapter diff --git a/tests/plugins/platforms/photon/test_mention_gating.py b/tests/plugins/platforms/photon/test_mention_gating.py index e352fee067..202936f993 100644 --- a/tests/plugins/platforms/photon/test_mention_gating.py +++ b/tests/plugins/platforms/photon/test_mention_gating.py @@ -15,7 +15,7 @@ from typing import List import pytest from gateway.config import PlatformConfig -from gateway.platforms.base import MessageEvent +from gateway.platforms.event import MessageEvent from plugins.platforms.photon.adapter import PhotonAdapter diff --git a/tests/plugins/platforms/photon/test_poll_clarify.py b/tests/plugins/platforms/photon/test_poll_clarify.py index 9897e755aa..20fdf3b78c 100644 --- a/tests/plugins/platforms/photon/test_poll_clarify.py +++ b/tests/plugins/platforms/photon/test_poll_clarify.py @@ -18,7 +18,8 @@ from typing import Any, Dict, List, Optional, Tuple import pytest from gateway.config import PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, SendResult +from gateway.platforms.base import SendResult +from gateway.platforms.event import MessageEvent, MessageType from plugins.platforms.photon.adapter import PhotonAdapter diff --git a/tests/plugins/platforms/photon/test_reactions.py b/tests/plugins/platforms/photon/test_reactions.py index 8b7105efcd..87c690bf91 100644 --- a/tests/plugins/platforms/photon/test_reactions.py +++ b/tests/plugins/platforms/photon/test_reactions.py @@ -13,7 +13,7 @@ from typing import Any, Dict, List, Tuple import pytest from gateway.config import PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType, ProcessingOutcome +from gateway.platforms.event import MessageEvent, MessageType, ProcessingOutcome from plugins.platforms.photon.adapter import PhotonAdapter _EYES = "\U0001f440" diff --git a/tests/plugins/platforms/photon/test_rich_links.py b/tests/plugins/platforms/photon/test_rich_links.py index 82306bb699..9cd8d5611f 100644 --- a/tests/plugins/platforms/photon/test_rich_links.py +++ b/tests/plugins/platforms/photon/test_rich_links.py @@ -13,7 +13,7 @@ from typing import Any, Dict, List, Tuple import pytest from gateway.config import PlatformConfig -from gateway.platforms.base import MessageEvent, MessageType +from gateway.platforms.event import MessageEvent, MessageType from plugins.platforms.photon import adapter as photon_adapter from plugins.platforms.photon.adapter import PhotonAdapter diff --git a/tests/plugins/test_a2a_plugin.py b/tests/plugins/test_a2a_plugin.py index 70751050e2..6c19b80ddf 100644 --- a/tests/plugins/test_a2a_plugin.py +++ b/tests/plugins/test_a2a_plugin.py @@ -618,7 +618,7 @@ class TestReplyCapture: def test_on_processing_complete_resolves_failure(self): """A failed run must resolve the future promptly (no reply timeout wait).""" - from gateway.platforms.base import ProcessingOutcome + from gateway.platforms.event import ProcessingOutcome adapter = _bare_adapter() fut = adapter._add_pending("task-fail", "ctx-fail") @@ -635,7 +635,7 @@ class TestReplyCapture: adapter._pop_pending("task-fail") def test_on_processing_complete_does_not_clobber_reply(self): - from gateway.platforms.base import ProcessingOutcome + from gateway.platforms.event import ProcessingOutcome adapter = _bare_adapter() fut = adapter._add_pending("task-ok", "ctx-ok") diff --git a/tests/tools/test_mcp_elicitation.py b/tests/tools/test_mcp_elicitation.py index dd5fe9d36b..d9dddb5313 100644 --- a/tests/tools/test_mcp_elicitation.py +++ b/tests/tools/test_mcp_elicitation.py @@ -206,7 +206,7 @@ class TestElicitationHandlerWiring: class TestElicitationHandlerContextBridge: """The MCP recv-loop task that fires elicitation callbacks does NOT inherit the agent's contextvars (HERMES_SESSION_PLATFORM etc.). The - handler reads ``owner._pending_call_context`` -- a snapshot captured + handler reads the ``call_context`` thunk's snapshot -- a snapshot captured by the MCP tool wrapper around ``session.call_tool`` -- and replays it before invoking the approval router so gateway-session detection survives the task hop. Regression tests for that bridge.""" @@ -217,7 +217,6 @@ class TestElicitationHandlerContextBridge: gateway-platform detection in approval.py sees an empty platform string and falls back to the CLI path (the bug this fixes).""" import contextvars - from types import SimpleNamespace probe: contextvars.ContextVar[str] = contextvars.ContextVar( "elicitation_test_probe", default="" @@ -238,8 +237,7 @@ class TestElicitationHandlerContextBridge: "context, otherwise the test would pass even without replay." ) - owner = SimpleNamespace(_pending_call_context=captured) - handler = ElicitationHandler("pay", {"timeout": 5}, owner=owner) + handler = ElicitationHandler("pay", {"timeout": 5}, call_context=lambda: captured) params = _form_params() with patch("tools.approval_prompt.request_elicitation_consent", side_effect=fake_consent): @@ -252,11 +250,11 @@ class TestElicitationHandlerContextBridge: ) def test_missing_captured_context_falls_back_to_direct_call(self): - """Without an owner (or with an owner that hasn't entered a tool + """Without a call_context (or one whose task hasn't entered a tool call) the handler must still invoke the consent router -- just without the contextvar replay. Otherwise CLI/TUI sessions, which don't set HERMES_SESSION_PLATFORM, would break.""" - handler = ElicitationHandler("pay", {"timeout": 5}, owner=None) + handler = ElicitationHandler("pay", {"timeout": 5}, call_context=None) params = _form_params() with patch("tools.approval_prompt.request_elicitation_consent", return_value="accept") as m: @@ -267,12 +265,9 @@ class TestElicitationHandlerContextBridge: def test_pending_call_context_none_does_not_crash(self): - """``owner._pending_call_context`` is set to None between tool + """The ``call_context`` thunk returns None between tool calls. An elicitation arriving in that window must not crash.""" - from types import SimpleNamespace - - owner = SimpleNamespace(_pending_call_context=None) - handler = ElicitationHandler("pay", {"timeout": 5}, owner=owner) + handler = ElicitationHandler("pay", {"timeout": 5}, call_context=lambda: None) params = _form_params() with patch("tools.approval_prompt.request_elicitation_consent", return_value="decline"): diff --git a/tools/mcp_tool_sampling.py b/tools/mcp_tool_sampling.py index fa19a5be77..4ce8c96629 100644 --- a/tools/mcp_tool_sampling.py +++ b/tools/mcp_tool_sampling.py @@ -4,11 +4,12 @@ from __future__ import annotations import asyncio +import functools import json import logging import time from contextvars import Context -from typing import Callable, List, Optional, Protocol +from typing import Callable, List, Optional from tools.mcp_tool_common import _MISSING, _exc_str, _safe_numeric, _sanitize_error, mcp_field, _core from tools.mcp_tool_schema import _normalize_mcp_input_schema @@ -242,13 +243,6 @@ def _format_elicitation_schema_summary(schema: dict, server_name: str) -> str: return "\n".join(lines) -class ElicitationOwner(Protocol): - """The server task an ElicitationHandler belongs to (tools.mcp_tool.MCPServerTask, which imports this - module, so it cannot be named here). Only the captured agent contextvars are read.""" - - _pending_call_context: Optional[Context] - - class ElicitationHandler: """``elicitation_callback`` for one MCP server. Form-mode routes through Hermes' approval system (CLI, TUI, Telegram, ...); URL-mode is declined. Fail-closed: any timeout, exception or unexpected @@ -260,12 +254,14 @@ class ElicitationHandler: # consent answer -> (ElicitResult action, metric); anything else declines. _ANSWER_RESULTS = {"accept": ("accept", "accepted"), "cancel": ("cancel", "errors")} - def __init__(self, server_name: str, config: dict, owner: Optional[ElicitationOwner] = None): + def __init__(self, server_name: str, config: dict, + call_context: Optional[Callable[[], Optional[Context]]] = None): self.server_name = server_name # 5 min mirrors the gateway approval default so async surfaces (Telegram, Slack) can respond. self.timeout = _safe_numeric(config.get("timeout", 300), 300, float) - # Back-reference for the agent's contextvars snapshot; optional for isolated unit tests. - self.owner = owner + # Returns the owning MCPServerTask's contextvars snapshot for the in-flight tool call (None + # between calls). A thunk, not the task: the task module imports this one. + self._call_context = call_context self.metrics = {"requests": 0, "accepted": 0, "declined": 0, "errors": 0} def session_kwargs(self) -> dict: @@ -278,16 +274,15 @@ class ElicitationHandler: return _core.ElicitResult(action=action, **({"content": {}} if action == "accept" else {})) def _consent_thunk(self, message: str, description: str) -> Callable[[], str]: - """Sync consent call replaying the agent's contextvars snapshot when the owner captured one + """Sync consent call replaying the agent's contextvars snapshot when the owning task captured one (the recv-loop task does NOT inherit them; gateway-platform detection needs them). ``Context.run`` runs a context once, so it is copied per elicitation.""" from tools.approval_prompt import request_elicitation_consent - kwargs = {"timeout_seconds": int(self.timeout), "surface": f"mcp-elicitation/{self.server_name}"} - captured = getattr(self.owner, "_pending_call_context", None) if self.owner else None - if captured is None: - return lambda: request_elicitation_consent(message, description, **kwargs) - return lambda: captured.copy().run(request_elicitation_consent, message, description, **kwargs) + consent = functools.partial(request_elicitation_consent, message, description, + timeout_seconds=int(self.timeout), surface=f"mcp-elicitation/{self.server_name}") + captured = self._call_context() if self._call_context else None + return consent if captured is None else (lambda: captured.copy().run(consent)) async def __call__(self, context, params): """SDK elicitation callback (``ElicitationFnT``). Returns ElicitResult or ErrorData.""" diff --git a/tools/mcp_tool_server_run.py b/tools/mcp_tool_server_run.py index 5cb8fe17cf..20ff8e770a 100644 --- a/tools/mcp_tool_server_run.py +++ b/tools/mcp_tool_server_run.py @@ -161,7 +161,8 @@ class MCPServerRunMixin: # elicitation/create lets a server ask for structured input mid-call; the handler # routes it through Hermes' approval system. elicitation_config = config.get("elicitation", {}) - self._elicitation = (_sampling.ElicitationHandler(self.name, elicitation_config, owner=self) + self._elicitation = (_sampling.ElicitationHandler(self.name, elicitation_config, + call_context=lambda: self._pending_call_context) if elicitation_config.get("enabled", True) and _core._MCP_ELICITATION_TYPES else None) if "url" in config and "command" in config: logger.warning("MCP server '%s' has both 'url' and 'command' in config. Using HTTP transport " diff --git a/website/docs/developer-guide/adding-platform-adapters.md b/website/docs/developer-guide/adding-platform-adapters.md index 6415baa6b1..7ae1f1567d 100644 --- a/website/docs/developer-guide/adding-platform-adapters.md +++ b/website/docs/developer-guide/adding-platform-adapters.md @@ -93,9 +93,8 @@ be granted its own outbound tools. ```python import os -from gateway.platforms.base import ( - BasePlatformAdapter, SendResult, MessageEvent, MessageType, -) +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.config import Platform, PlatformConfig @@ -574,9 +573,8 @@ Create `plugins/platforms/newplat/adapter.py`: ```python from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, SendResult, -) +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType def check_newplat_requirements() -> bool: """Return True if dependencies are available.""" diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/adding-platform-adapters.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/adding-platform-adapters.md index b52870e848..0a50ce8afa 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/adding-platform-adapters.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/adding-platform-adapters.md @@ -65,9 +65,8 @@ optional_env: ```python import os -from gateway.platforms.base import ( - BasePlatformAdapter, SendResult, MessageEvent, MessageType, -) +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType from gateway.config import Platform, PlatformConfig @@ -476,9 +475,8 @@ class Platform(str, Enum): ```python from gateway.config import Platform, PlatformConfig -from gateway.platforms.base import ( - BasePlatformAdapter, MessageEvent, MessageType, SendResult, -) +from gateway.platforms.base import BasePlatformAdapter, SendResult +from gateway.platforms.event import MessageEvent, MessageType def check_newplat_requirements() -> bool: """如果依赖可用则返回 True。"""