fix(teams): package Microsoft Teams SDK as an installable extra (salvage #43945) (#46764)

* fix(teams): package Microsoft Teams SDK as an installable extra

The Teams adapter imports the microsoft-teams-apps SDK, but it was never
declared as a dependency, so source/local installs hit ImportError and the
adapter silently reported the SDK as unavailable. Add a 'teams' extra
(microsoft-teams-apps==2.0.13.4 + aiohttp) and document 'uv sync --extra teams'.

Per the 2026-05-12 [all] policy, opt-in messaging-platform SDKs are NOT added
to [all] (they would break every fresh install on a quarantined release); the
teams extra is installed on demand like the other platform backends.

Co-authored-by: rio-jeong <rio.jeong@thebytesize.ai>

* chore: map rio-jeong contributor email for attribution (#43945)

* feat(teams): lazy-install the Teams SDK on demand (parity with other channels)

The teams extra alone left Teams as the only messaging platform that wouldn't
auto-install its SDK — every other channel (telegram, discord, slack, matrix,
dingtalk, feishu) lazy-installs via tools.lazy_deps on first connect. Bring
Teams to parity:

- Add 'platform.teams' to LAZY_DEPS (microsoft-teams-apps + aiohttp).
- Replace the passive 'check_teams_requirements = check_requirements' alias with
  a real lazy-installer that calls ensure_and_bind('platform.teams', ...),
  rebinding all Teams SDK globals on success (mirrors check_slack_requirements).
- Call check_teams_requirements() at the top of TeamsAdapter.connect() so
  enabling Teams installs the SDK on demand.
- Keep the passive check_requirements() as the registry check_fn so 'gateway
  status' probes never trigger a pip install.

The 'teams' extra remains for packagers / explicit 'uv sync --extra teams'.

Tests: rework the alias test into shortcircuit + lazy-install assertions, and
update test_connect_fails_without_sdk to simulate an uninstallable SDK.

---------

Co-authored-by: rio-jeong <rio.jeong@thebytesize.ai>
Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
This commit is contained in:
Austin Pickett 2026-06-15 14:35:15 -04:00 committed by CodeForgeNet
parent 78a415b6bb
commit 97bbe33c81
7 changed files with 211 additions and 4 deletions

View file

@ -211,10 +211,39 @@ class TestTeamsRequirements:
monkeypatch.setattr(_teams_mod, "AIOHTTP_AVAILABLE", True)
assert check_requirements() is True
def test_alias_matches(self, monkeypatch):
def test_check_teams_requirements_shortcircuits_when_present(self, monkeypatch):
# When the SDK + aiohttp are already importable, the active lazy-
# installer returns True immediately without attempting an install.
monkeypatch.setattr(_teams_mod, "TEAMS_SDK_AVAILABLE", True)
monkeypatch.setattr(_teams_mod, "AIOHTTP_AVAILABLE", True)
called = {"ensure_and_bind": 0}
def _fake_ensure_and_bind(*_args, **_kwargs):
called["ensure_and_bind"] += 1
return True
monkeypatch.setattr(
"tools.lazy_deps.ensure_and_bind", _fake_ensure_and_bind
)
assert check_teams_requirements() is True
assert called["ensure_and_bind"] == 0
def test_check_teams_requirements_lazy_installs_when_missing(self, monkeypatch):
# When deps are missing, the active installer delegates to
# ensure_and_bind("platform.teams", ...) — parity with Slack/Discord.
monkeypatch.setattr(_teams_mod, "TEAMS_SDK_AVAILABLE", False)
monkeypatch.setattr(_teams_mod, "AIOHTTP_AVAILABLE", False)
seen = {}
def _fake_ensure_and_bind(feature, importer, target_globals, **kwargs):
seen["feature"] = feature
return True
monkeypatch.setattr(
"tools.lazy_deps.ensure_and_bind", _fake_ensure_and_bind
)
assert check_teams_requirements() is True
assert seen["feature"] == "platform.teams"
def test_validate_config_with_env(self, monkeypatch):
monkeypatch.setenv("TEAMS_CLIENT_ID", "test-id")
@ -371,6 +400,13 @@ class TestTeamsConnect:
@pytest.mark.anyio
async def test_connect_fails_without_sdk(self, monkeypatch):
monkeypatch.setattr(_teams_mod, "TEAMS_SDK_AVAILABLE", False)
# Simulate the SDK being unavailable AND not installable (offline /
# locked-down env): the lazy-installer can't rebind the globals, so
# TEAMS_SDK_AVAILABLE stays False and connect() must fail.
monkeypatch.setattr(
"tools.lazy_deps.ensure_and_bind",
lambda *_a, **_k: False,
)
adapter = TeamsAdapter(_make_config(
client_id="id", client_secret="secret", tenant_id="tenant",
))