fix(gateway): add lazy_deps.ensure() to slack, matrix, dingtalk, feishu adapters (#25014)

Only Discord and Telegram had lazy-install hooks in their
check_*_requirements() functions. The remaining four platforms that were
moved to lazy_deps (Slack, Matrix, DingTalk, Feishu) would just return
False immediately if their packages weren't pre-installed — no attempt
to install them at runtime.

This means even with the .venv permissions fix (#24841), these four
platforms would still fail to load in Docker (or any fresh install)
unless the user manually ran pip install.

Add the same lazy_deps.ensure() pattern to all four, matching the
existing Discord/Telegram implementation.
This commit is contained in:
Siddharth Balyan 2026-05-13 19:28:50 +05:30 committed by GitHub
parent c3094b46e9
commit 5d90386baa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 84 additions and 11 deletions

View file

@ -111,9 +111,33 @@ DINGTALK_TYPE_MAPPING = {
def check_dingtalk_requirements() -> bool:
"""Check if DingTalk dependencies are available and configured."""
"""Check if DingTalk dependencies are available and configured.
Lazy-installs dingtalk-stream via ``tools.lazy_deps.ensure("platform.dingtalk")``
on first call if not present.
"""
global DINGTALK_STREAM_AVAILABLE, dingtalk_stream, ChatbotMessage, CallbackMessage, AckMessage
global HTTPX_AVAILABLE, httpx
if not DINGTALK_STREAM_AVAILABLE or not HTTPX_AVAILABLE:
return False
try:
from tools.lazy_deps import ensure as _lazy_ensure
_lazy_ensure("platform.dingtalk", prompt=False)
except Exception:
return False
try:
import dingtalk_stream as _ds
from dingtalk_stream import ChatbotMessage as _CM
from dingtalk_stream.frames import CallbackMessage as _CBM, AckMessage as _AM
import httpx as _httpx
except ImportError:
return False
dingtalk_stream = _ds
ChatbotMessage = _CM
CallbackMessage = _CBM
AckMessage = _AM
httpx = _httpx
DINGTALK_STREAM_AVAILABLE = True
HTTPX_AVAILABLE = True
if not os.getenv("DINGTALK_CLIENT_ID") or not os.getenv("DINGTALK_CLIENT_SECRET"):
return False
return True

View file

@ -1343,8 +1343,25 @@ def _run_official_feishu_ws_client(ws_client: Any, adapter: Any) -> None:
def check_feishu_requirements() -> bool:
"""Check if Feishu/Lark dependencies are available."""
return FEISHU_AVAILABLE
"""Check if Feishu/Lark dependencies are available.
Lazy-installs lark-oapi via ``tools.lazy_deps.ensure("platform.feishu")``
on first call if not present.
"""
global FEISHU_AVAILABLE
if FEISHU_AVAILABLE:
return True
try:
from tools.lazy_deps import ensure as _lazy_ensure
_lazy_ensure("platform.feishu", prompt=False)
except Exception:
return False
try:
import lark_oapi # noqa: F401
except ImportError:
return False
FEISHU_AVAILABLE = True
return True
class FeishuAdapter(BasePlatformAdapter):

View file

@ -224,7 +224,11 @@ def _check_e2ee_deps() -> bool:
def check_matrix_requirements() -> bool:
"""Return True if the Matrix adapter can be used."""
"""Return True if the Matrix adapter can be used.
Lazy-installs mautrix via ``tools.lazy_deps.ensure("platform.matrix")``
on first call if not present.
"""
token = os.getenv("MATRIX_ACCESS_TOKEN", "")
password = os.getenv("MATRIX_PASSWORD", "")
homeserver = os.getenv("MATRIX_HOMESERVER", "")
@ -238,10 +242,15 @@ def check_matrix_requirements() -> bool:
try:
import mautrix # noqa: F401
except ImportError:
logger.warning(
"Matrix: mautrix not installed. Run: pip install 'mautrix[encryption]'"
)
return False
try:
from tools.lazy_deps import ensure as _lazy_ensure
_lazy_ensure("platform.matrix", prompt=False)
import mautrix # noqa: F401, F811
except Exception:
logger.warning(
"Matrix: mautrix not installed. Run: pip install 'mautrix[encryption]'"
)
return False
# If encryption is requested, verify E2EE deps are available at startup
# rather than silently degrading to plaintext-only at connect time.

View file

@ -73,8 +73,30 @@ class _ThreadContextCache:
def check_slack_requirements() -> bool:
"""Check if Slack dependencies are available."""
return SLACK_AVAILABLE
"""Check if Slack dependencies are available.
Lazy-installs slack-bolt/slack-sdk via ``tools.lazy_deps.ensure("platform.slack")``
on first call if not present.
"""
global SLACK_AVAILABLE, AsyncApp, AsyncSocketModeHandler, AsyncWebClient
if SLACK_AVAILABLE:
return True
try:
from tools.lazy_deps import ensure as _lazy_ensure
_lazy_ensure("platform.slack", prompt=False)
except Exception:
return False
try:
from slack_bolt.async_app import AsyncApp as _App
from slack_bolt.adapter.socket_mode.async_handler import AsyncSocketModeHandler as _Handler
from slack_sdk.web.async_client import AsyncWebClient as _Client
except ImportError:
return False
AsyncApp = _App
AsyncSocketModeHandler = _Handler
AsyncWebClient = _Client
SLACK_AVAILABLE = True
return True
def _extract_text_from_slack_blocks(blocks: list) -> str: