* feat(hosting-activity-protocol): rename Bot Framework channel to ActivityProtocolChannel
The existing Bot-Framework-via-Azure-Bot-Service channel was previously
shipped under the name ``hosting-teams`` / ``TeamsChannel``. That name
is misleading for what the channel actually does -- it speaks the Bot
Framework Activity Protocol against Azure Bot Service, which fans out
across MS Teams, Slack, Webex, Telegram-via-Bot-Service, etc., and does
not provide any Teams-specific affordances.
This PR renames the package atomically and frees the ``hosting-teams``
name for a future Teams-native channel built on
``microsoft-teams-apps`` (PR-5b, spec req #28).
Renames (all in one commit):
- Package: ``agent-framework-hosting-teams`` ->
``agent-framework-hosting-activity-protocol``
- Module: ``agent_framework_hosting_teams`` ->
``agent_framework_hosting_activity_protocol``
- Channel class: ``TeamsChannel`` -> ``ActivityProtocolChannel``
- Helper: ``teams_isolation_key`` -> ``activity_protocol_isolation_key``
(isolation key prefix ``teams:`` -> ``activity:``)
- Channel name: ``"teams"`` -> ``"activity"``; default mount path
``/teams`` -> ``/activity``
- Internal helper: ``_parse_teams_activity`` -> ``_parse_activity``
- Worker task name + a couple of error strings updated for consistency
Updates README.md and the module docstring to call out:
- this is the channel-neutral Activity Protocol channel,
- it surfaces what every Bot-Service-connected channel has in common
(text in / text out),
- a forthcoming ``agent-framework-hosting-teams`` package will layer
Teams-specific affordances (adaptive cards, message extensions,
dialogs, SSO, ...) on the same Bot Service transport.
Workspace: registers ``agent-framework-hosting-activity-protocol`` in
``python/pyproject.toml`` and adds the matching pyright
``executionEnvironments`` entry.
Behavior is unchanged. Pyright + mypy clean, 11 tests pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* review: address PR-5 round 2 feedback
- security (#3198327004): add `service_url_allowed_hosts` constructor
option (default `botframework.com` + `smba.trafficmanager.net`) and
reject inbound activities whose `serviceUrl` host falls outside it
with HTTP 400 — without this gate a malicious caller could redirect
outbound replies (and the attached bearer token) to an
attacker-controlled host
- security (#3198324219): add `inbound_auth_validator` async callback;
log a loud WARNING at startup when no validator AND no operator
reverse-proxy is configured so the dev-mode bypass cannot
accidentally ship to production. Document the contract: prototype
intentionally does not ship JWT validation (out of scope); operators
must plug a validator or terminate auth in front of the channel
- retry semantics (#3198328746): distinguish transient outbound
failures (httpx network errors, non-2xx from Bot Service) — return
502 so Bot Service retries — from deterministic agent failures —
return 200 so Bot Service does not retry the same broken activity
in a loop
- bug (#3198330424): fix the placeholder-failure deadlock. When
`send_initial_placeholder` fails, `activity_id` stays `None`, the
edit-worker loop exit condition (`accumulated == last_sent`) is
unreachable while no PUT is possible, and the worker would deadlock
on `wake.wait()` forever after `worker_done` is set. Now: skip the
worker entirely on placeholder failure and POST a single final
activity at the end with whatever accumulated
- tests (#3198334465, #3187178091, #3198336045): add coverage for
- `_is_service_url_allowed` allow/deny matrix + webhook 400 on
disallowed serviceUrl
- `inbound_auth_validator` allow/deny/raises paths
- outbound `Authorization: Bearer <token>` header presence in
production mode and absence in dev mode
- the streaming path (`_stream_to_conversation`): placeholder +
final edit, placeholder-failure fallback (with timeout guard
against deadlock regression), and empty-stream `(no response)`
placeholder replacement
- retry-signal differentiation: outbound `httpx.ConnectError` →
502; deterministic `ValueError` from the agent → 200
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test(hosting): drop redundant @pytest.mark.asyncio decorators
asyncio_mode = "auto" is configured in pyproject.toml across the
hosting packages, so individual @pytest.mark.asyncio decorators are
unnecessary.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(hosting-activity-protocol): add response hooks
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs(hosting-activity-protocol): mark constructor keyword args
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>