Skip to content

Porting methods to check feature support across channels - #580

Merged
Rodrigo Brandão (rodrigobr-msft) merged 9 commits into
mainfrom
users/robrandao/channel-helpers
Sep 14, 2026
Merged

Rodrigo Brandão (rodrigobr-msft) merged 9 commits into
mainfrom
users/robrandao/channel-helpers

Conversation

@rodrigobr-msft

@rodrigobr-msft Rodrigo Brandão (rodrigobr-msft) commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

This pull request enhances the Channels helper functionality to provide a unified way to check per-channel feature support, improves type handling and normalization of channel IDs, and introduces comprehensive tests for these helpers. It also adds new channel enum values and improves backwards compatibility for the Teams channel. Additionally, it documents these changes in the changelog.

Channel feature support helpers:

  • Added static methods to Channels for checking support of various features (e.g., supports_card_actions, supports_suggested_actions, supports_video_card, supports_receipt_card, supports_thumbnail_card, supports_audio_card, supports_animation_card, supports_create_conversation, supports_update_activity, supports_delete_activity), all of which accept Channels, ChannelId, or plain string inputs and normalize them internally. [1] [2]
  • Improved and unified handling of channel ID normalization, so all helpers work with different input types and sub-channel forms.

Enum and backwards compatibility:

  • Added new enum members to Channels (e.g., alexa, twilio) and made ms_teams a deprecated alias of msteams for backwards compatibility, ensuring consistent usage and migration support. [1] [2] [3] [4]

Testing:

  • Added a comprehensive test suite (test_channels.py) to verify all feature support helpers, channel ID normalization, and backwards compatibility for the Teams channel.

Documentation:

  • Updated the changelog.md to document the new channel feature support helpers and their usage.

Copilot AI lite review requested due to automatic review settings September 14, 2026 17:27
@rodrigobr-msft
Rodrigo Brandão (rodrigobr-msft) marked this pull request as ready for review September 14, 2026 17:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Empty IDs can raise instead of returning False, and the legacy choice path still uses a divergent capability table.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Ports channel feature-support checks into Channels, with channel ID normalization, aliases, and expanded tests.

Changes:

  • Adds capability checks and Alexa/Twilio identifiers.
  • Supports sub-channel IDs and ms_teams compatibility.
  • Adds parameterized tests for formats, aliases, and capability limits.
File summaries
File Reviewed changes Final review comments
tests/activity/test_channels.py Adds coverage for aliases, channel formats, sub-channels, and capability limits. —
libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py Implements channel normalization and capability checks. Moderate (2 votes): Guard empty IDs before constructing ChannelId.
Moderate (1 vote): Align the legacy Channel path with these capability checks.
Nit (3 votes): Rename the docstring parameter directive from _ to channel_id.
Nit (1 vote): Correct the new docstring grammar.
Review details

Suppressed comments (2)

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:103

  • The parameter description uses “checks” after the infinitive “to”; correct the grammar in this newly added docstring.
        :param channel_id: The ID of the channel to checks for support of Suggested Actions.

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:100

  • The existing production path still calls hosting.dialogs.choices.Channel from ChoiceFactory (choice_factory.py:58-62), so these new implementations are not used by current choice rendering. This leaves two divergent capability tables—for example, Teams remains limited to 3 card actions in the old path while this port allows 50—and future updates can drift. Please make the old Channel delegate to Channels or update its callers as part of this port.
    def supports_suggested_actions(
        channel_id: str, button_cnt: int = 100, conversation_type: str | None = None
    ) -> bool:
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py Outdated
Comment thread libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py Outdated
Copilot AI review requested due to automatic review settings September 14, 2026 17:31
@rodrigobr-msft Rodrigo Brandão (rodrigobr-msft) linked an issue Sep 14, 2026 that may be closed by this pull request

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved moderate compatibility issues remain, along with changelog and boundary-test nits.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (2)

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:95

  • ChannelId rejects empty or whitespace values, so this raises TypeError for "" instead of returning an unsupported result. That is a compatibility regression for the existing channel-id path, where Channel.get_channel_id returns "" when the activity has no channel and the old support helpers returned False; handle missing IDs with a non-throwing, consistently defined fallback.
    tests/activity/test_channels.py:38
  • The changed Teams card-action limit is not tested at its boundary: these assertions would also pass for limits such as 4 or 99. Please assert that 50 is accepted and 51 is rejected so the new limit is regression-tested.
        assert Channels.supports_card_actions(channel_id, 3) is True
        assert Channels.supports_card_actions(channel_id, 100) is False
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py Outdated
Comment thread changelog.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Unresolved moderate issues remain in the thumbnail-card denylist, Teams boundary tests, and duplicated changelog entry.

Review details

Suppressed comments (6)

Previously missed (2) — in code that hasn't changed since the last review.

tests/activity/test_channels.py:38

  • These assertions do not protect the changed Teams limit of 50: values 3 and 100 would also pass if the implementation used any limit from 3 through 99. Add boundary checks for 50 (true) and 51 (false) while retaining the format coverage.

This issue also appears on line 50 of the same file.
libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:102

  • to checks is grammatically incorrect in this new docstring; use to check.

changelog.md:14

  • This adds a second ## Bug Fixes section and duplicates the existing Typing Indicator entry immediately below it. Remove this added block so the release notes contain the fix only once.
## Bug Fixes

- **Typing Indicator on Update/Delete**: Fixed the typing indicator re-appearing in Teams clients after the finalized streaming activity was updated or deleted post-`end_stream()`.

changelog.md:10

  • This release note uses the grammatical form "Adding" for an already delivered API. Change it to "Added" so the changelog consistently describes released changes.
- **Channel Feature Support Helpers**: Adding `Channels` helper methods (e.g. `supports_card_actions`, `supports_suggested_actions`, `supports_video_card`, `supports_receipt_card`, `supports_thumbnail_card`, `supports_audio_card`, `supports_animation_card`, `supports_create_conversation`, `supports_update_activity`, `supports_delete_activity`) for checking per-channel feature support, accepting `Channels`, `ChannelId`, and plain string inputs (#580)

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:199

  • The thumbnail-card denylist omits groupme, line, and slack, so these text-only channels currently return True (including for sub-channel IDs) even though they cannot render thumbnail cards. Add the missing channel values and cover them in the tests.
        return channel not in (
            Channels.alexa.value,
            Channels.msteams.value,
            Channels.twilio.value,
        )

tests/activity/test_channels.py:51

  • The new Teams-specific suggested-action limit is only tested at 3, so a regression that allowed 4 or more actions would go undetected. Add a personal-conversation assertion for 4 actions returning False.
        assert Channels.supports_suggested_actions(channel_id, 3, "personal") is True
        assert Channels.supports_suggested_actions(channel_id, 3) is False
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical and moderate findings remain, including Teams API inconsistencies, typing gaps, test coverage gaps, and duplicate changelog content.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (6)

changelog.md:14

  • These added lines duplicate the existing ## Bug Fixes section and repeat the Typing Indicator on Update/Delete entry already present at lines 16-18. Remove the newly added three-line Bug Fixes block so the unreleased changelog contains one heading and one entry.
## Bug Fixes

- **Typing Indicator on Update/Delete**: Fixed the typing indicator re-appearing in Teams clients after the finalized streaming activity was updated or deleted post-`end_stream()`.

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:146

  • The new 50-action Teams limit also conflicts with the still-live hosting.dialogs.choices.Channel.supports_card_actions, which remains capped at 3 and is what ChoiceFactory calls. Thus existing Teams choice rendering falls back to a numbered list for 4–50 actions even though this helper says CardActions are supported; consolidate the two implementations so the new limit is actually honored.
        max_actions = {
            Channels.facebook.value: 3,
            Channels.skype.value: 3,
            Channels.msteams.value: 50,

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:99

  • _normalize_channel_id accepts Channels and ChannelId, and the tests pass both, but this public signature is still annotated as str (as are the other new helpers). Typed consumers will therefore get an error when using the supported inputs described by the PR. Change every public helper's channel_id annotation to str | Channels | ChannelId (or a shared alias).
        channel_id: str, button_cnt: int = 100, conversation_type: str | None = None
    ) -> bool:

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:170

  • The new alexa/twilio exclusions are only covered indirectly for Alexa in supports_create_conversation; no test passes twilio (or a Twilio sub-channel) through any card helper. Since these enum values and normalization paths are new, add parametrized Twilio cases to make the blacklist behavior regression-safe.
            Channels.alexa.value,
            Channels.msteams.value,
            Channels.twilio.value,
        )

tests/activity/test_channels.py:120

  • This test covers only the Teams-positive path. Because supports_update_activity is intended to be channel-specific, add a non-Teams assertion so a regression that returns True for every channel is detected.
    def test_supports_update_activity_returns_true_for_msteams(self, channel_id):
        assert Channels.supports_update_activity(channel_id) is True

tests/activity/test_channels.py:128

  • This test covers only the Teams-positive path even though supports_delete_activity uses a three-channel allowlist. Add a non-supported-channel assertion so accidental support for every channel is detected.
    def test_supports_delete_activity_returns_true_for_msteams(self, channel_id):
        assert Channels.supports_delete_activity(channel_id) is True
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Unresolved moderate issues remain in capability alignment, public type annotations, and boundary test coverage.

Review details

Suppressed comments (4)

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:146

  • This creates a second source of truth that conflicts with the existing helper used by ChoiceFactory: choice_factory.py:61 still calls hosting.dialogs.choices.Channel.supports_card_actions, whose Teams cap is 3. As a result, the new 50-action capability is not reflected in automatic choice rendering for 4–50 Teams choices. Please delegate the legacy helper/consumer to this table or otherwise centralize and align the limits.
            Channels.msteams.value: 50,

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:99

  • The public contract says these helpers accept Channels and ChannelId, and the new tests pass both, but this signature advertises only str, so type checkers reject valid callers. Please use a shared str | Channels | ChannelId input type on every public helper to keep the annotations aligned with the runtime behavior and changelog.
    def supports_suggested_actions(
        channel_id: str, button_cnt: int = 100, conversation_type: str | None = None
    ) -> bool:

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:102

  • The channel_id parameter description uses the ungrammatical phrase “to checks”; change it to “to check” so the new public API documentation is clear.
        :param channel_id: The ID of the channel to checks for support of Suggested Actions.

tests/activity/test_channels.py:44

  • The test comment says Teams supports up to 50 actions, but these assertions only exercise 3 and 100. They would still pass if the implementation retained the old limit of 3, so the new boundary is unprotected; add checks for 50 (true) and 51 (false).
        assert Channels.supports_card_actions(channel_id, 3) is True
        assert Channels.supports_card_actions(channel_id, 100) is False
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved missing-channel handling and conflicting Teams limit tests prevent approval.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (1)

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:94

  • Constructing ChannelId here raises TypeError for an empty channel ID. ChoiceFactory.for_channel explicitly converts a missing channel (None) to "" before calling the legacy Channel helpers, so this delegation now makes that supported fallback path fail instead of returning False and choosing an inline/list format. Normalize with the existing optional-safe ChannelId.get_channel (or otherwise handle empty IDs) so unknown/missing channels do not raise.
        return ChannelId(channel_id).channel
  • Files reviewed: 4/4 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py Outdated
Copilot AI review requested due to automatic review settings September 14, 2026 19:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The empty channel ID fallback can currently cause prompt failures, and two docstrings exceed the configured line-length limit.

Review details

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:92

  • ChoiceFactory.for_channel deliberately converts a missing channel ID to "" before these helpers are called, and the prompt callers pass activity.channel_id or "". Constructing ChannelId with that value raises TypeError, so prompts with no channel ID now fail instead of falling back to the existing inline/list rendering. Preserve the previous empty-channel behavior while normalizing valid sub-channel IDs.

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:103

  • This newly added docstring line is well over the repository's configured Flake8 limit of 127 characters (.flake8:2), so the lint job will report E501. Wrap the return description onto a second indented line.
        :returns: True if the Channel supports the button_cnt total Suggested Actions, False if the Channel does not support that number of Suggested Actions.

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:136

  • This newly added docstring line is well over the repository's configured Flake8 limit of 127 characters (.flake8:2), so the lint job will report E501. Wrap the return description onto a second indented line.
        :returns: True if the Channel supports the button_cnt total Card Actions, False if the Channel does not support that number of Card Actions.
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 14, 2026 19:28
@rodrigobr-msft
Rodrigo Brandão (rodrigobr-msft) merged commit e6f0088 into main Sep 14, 2026
10 of 11 checks passed
@rodrigobr-msft
Rodrigo Brandão (rodrigobr-msft) deleted the users/robrandao/channel-helpers branch September 14, 2026 19:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A critical missing-channel normalization issue can break choice creation, and two docstrings exceed the lint limit.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (2)

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:136

  • This newly added docstring line is well over the repository's 127-character flake8 limit, so it will fail the standard lint check. Wrap the return description across lines, as the existing choice helper docstrings do.
        :returns: True if the Channel supports the button_cnt total Card Actions, False if the Channel does not support that number of Card Actions.

libraries/microsoft-agents-activity/microsoft_agents/activity/channels.py:103

  • This newly added docstring line is well over the repository's 127-character flake8 limit, so it will fail the standard lint check. Wrap the return description across lines, as the existing choice helper docstrings do.
        :returns: True if the Channel supports the button_cnt total Suggested Actions, False if the Channel does not support that number of Suggested Actions.
  • Files reviewed: 5/5 changed files
  • Comments generated: 1
  • Review effort level: Lite

:param channel_id: The channel ID to normalize.
:returns: The canonical string representation of the channel ID.
"""
return ChannelId(channel_id).channel
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Port Channels utility methods from .NET

3 participants