diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/teams/teams_channel_account.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/teams/teams_channel_account.py index 0f06fa12..337a114b 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/teams/teams_channel_account.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/teams/teams_channel_account.py @@ -11,6 +11,10 @@ class TeamsChannelAccount(AgentsModel): :param id: Channel id for the user or bot on this channel (Example: ``joe@smith.com``, or ``@joesmith`` or ``123456``) :type id: str + :param aad_object_id: Azure Active Directory object id for the user. + :type aad_object_id: str + :param role: Role of the user in the channel. + :type role: str :param name: Display friendly name :type name: str :param given_name: Given name part of the user name. @@ -30,6 +34,8 @@ class TeamsChannelAccount(AgentsModel): model_config = ConfigDict(extra="allow") id: str = None + aad_object_id: str = None + role: str = None name: str = None given_name: str = None surname: str = None diff --git a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/activity_handler.py b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/activity_handler.py index 10827220..4235dc60 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/activity_handler.py +++ b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/activity_handler.py @@ -538,7 +538,7 @@ async def on_adaptive_card_invoke( raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) @staticmethod - def _create_invoke_response(body: BaseModel = None) -> InvokeResponse: + def _create_invoke_response(body: BaseModel | None = None) -> InvokeResponse: serialized_body = ( body.model_dump(mode="json", by_alias=True, exclude_none=True) if body diff --git a/libraries/microsoft-agents-hosting-teams/microsoft_agents/hosting/teams/teams_activity_handler.py b/libraries/microsoft-agents-hosting-teams/microsoft_agents/hosting/teams/teams_activity_handler.py index c0511e2d..2c171d5f 100644 --- a/libraries/microsoft-agents-hosting-teams/microsoft_agents/hosting/teams/teams_activity_handler.py +++ b/libraries/microsoft-agents-hosting-teams/microsoft_agents/hosting/teams/teams_activity_handler.py @@ -74,20 +74,24 @@ async def on_invoke_activity(self, turn_context: TurnContext) -> InvokeResponse: await self.on_teams_config_submit(turn_context, value) ) elif name == "fileConsent/invoke": + card_response = FileConsentCardResponse.model_validate(value) return self._create_invoke_response( - await self.on_teams_file_consent(turn_context, value) + await self.on_teams_file_consent(turn_context, card_response) ) elif name == "actionableMessage/executeAction": - await self.on_teams_o365_connector_card_action(turn_context, value) + query = O365ConnectorCardActionQuery.model_validate(value) + await self.on_teams_o365_connector_card_action(turn_context, query) return self._create_invoke_response() elif name == "composeExtension/queryLink": + query = AppBasedLinkQuery.model_validate(value) return self._create_invoke_response( - await self.on_teams_app_based_link_query(turn_context, value) + await self.on_teams_app_based_link_query(turn_context, query) ) elif name == "composeExtension/anonymousQueryLink": + query = AppBasedLinkQuery.model_validate(value) return self._create_invoke_response( await self.on_teams_anonymous_app_based_link_query( - turn_context, value + turn_context, query ) ) elif name == "composeExtension/query": @@ -104,21 +108,24 @@ async def on_invoke_activity(self, turn_context: TurnContext) -> InvokeResponse: ) ) elif name == "composeExtension/submitAction": + action = MessagingExtensionAction.model_validate(value) return self._create_invoke_response( await self.on_teams_messaging_extension_submit_action_dispatch( - turn_context, value + turn_context, action ) ) elif name == "composeExtension/fetchTask": + action = MessagingExtensionAction.model_validate(value) return self._create_invoke_response( await self.on_teams_messaging_extension_fetch_task( - turn_context, value + turn_context, action ) ) elif name == "composeExtension/querySettingUrl": + query = MessagingExtensionQuery.model_validate(value) return self._create_invoke_response( await self.on_teams_messaging_extension_configuration_query_setting_url( - turn_context, value + turn_context, query ) ) elif name == "composeExtension/setting": @@ -146,12 +153,14 @@ async def on_invoke_activity(self, turn_context: TurnContext) -> InvokeResponse: ) ) elif name == "tab/fetch": + tab_request = TabRequest.model_validate(value) return self._create_invoke_response( - await self.on_teams_tab_fetch(turn_context, value) + await self.on_teams_tab_fetch(turn_context, tab_request) ) elif name == "tab/submit": + tab_submit = TabSubmit.model_validate(value) return self._create_invoke_response( - await self.on_teams_tab_submit(turn_context, value) + await self.on_teams_tab_submit(turn_context, tab_submit) ) else: return await super().on_invoke_activity(turn_context) @@ -498,10 +507,8 @@ async def on_conversation_update_activity(self, turn_context: TurnContext): :return: None """ if turn_context.activity.channel_id == "msteams": - channel_data = ( - TeamsChannelData.model_validate(turn_context.activity.channel_data) - if turn_context.activity.channel_data - else None + channel_data = TeamsChannelData.model_validate( + turn_context.activity.channel_data ) if ( @@ -509,16 +516,18 @@ async def on_conversation_update_activity(self, turn_context: TurnContext): and len(turn_context.activity.members_added) > 0 ): return await self.on_teams_members_added_dispatch( - turn_context.activity.members_added, - channel_data.team if channel_data else None, - turn_context, + turn_context.activity.members_added, channel_data.team, turn_context ) if ( turn_context.activity.members_removed and len(turn_context.activity.members_removed) > 0 ): - return await self.on_teams_members_removed(turn_context) + return await self.on_teams_members_removed_dispatch( + turn_context.activity.members_removed, + channel_data.team, + turn_context, + ) if not channel_data or not channel_data.event_type: return await super().on_conversation_update_activity(turn_context) @@ -526,25 +535,41 @@ async def on_conversation_update_activity(self, turn_context: TurnContext): event_type = channel_data.event_type if event_type == "channelCreated": - return await self.on_teams_channel_created(turn_context) + return await self.on_teams_channel_created( + channel_data.channel, channel_data.team, turn_context + ) elif event_type == "channelDeleted": - return await self.on_teams_channel_deleted(turn_context) + return await self.on_teams_channel_deleted( + channel_data.channel, channel_data.team, turn_context + ) elif event_type == "channelRenamed": - return await self.on_teams_channel_renamed(turn_context) + return await self.on_teams_channel_renamed( + channel_data.channel, channel_data.team, turn_context + ) elif event_type == "teamArchived": - return await self.on_teams_team_archived(turn_context) + return await self.on_teams_team_archived( + channel_data.team, turn_context + ) elif event_type == "teamDeleted": - return await self.on_teams_team_deleted(turn_context) + return await self.on_teams_team_deleted(channel_data.team, turn_context) elif event_type == "teamHardDeleted": - return await self.on_teams_team_hard_deleted(turn_context) + return await self.on_teams_team_hard_deleted( + channel_data.team, turn_context + ) elif event_type == "channelRestored": - return await self.on_teams_channel_restored(turn_context) + return await self.on_teams_channel_restored( + channel_data.channel, channel_data.team, turn_context + ) elif event_type == "teamRenamed": - return await self.on_teams_team_renamed(turn_context) + return await self.on_teams_team_renamed(channel_data.team, turn_context) elif event_type == "teamRestored": - return await self.on_teams_team_restored(turn_context) + return await self.on_teams_team_restored( + channel_data.team, turn_context + ) elif event_type == "teamUnarchived": - return await self.on_teams_team_unarchived(turn_context) + return await self.on_teams_team_unarchived( + channel_data.team, turn_context + ) return await super().on_conversation_update_activity(turn_context) @@ -668,6 +693,7 @@ async def on_teams_members_added_dispatch( # Propagate any other errors raise + await self.on_members_added_activity(members_added, turn_context) await self.on_teams_members_added(teams_members_added, team_info, turn_context) async def on_teams_members_added( @@ -679,10 +705,12 @@ async def on_teams_members_added( """ Handles Teams members added. + :param teams_members_added: The list of TeamsChannelAccount objects representing the members added to the conversation. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ - await self.on_members_added_activity(teams_members_added, turn_context) + return async def on_teams_members_removed_dispatch( self, @@ -700,7 +728,9 @@ async def on_teams_members_removed_dispatch( member.model_dump(by_alias=True, exclude_unset=True) ) ) - return await self.on_teams_members_removed( + + await self.on_members_removed_activity(members_removed, turn_context) + await self.on_teams_members_removed( teams_members_removed, team_info, turn_context ) @@ -713,10 +743,12 @@ async def on_teams_members_removed( """ Handles Teams members removed. + :param teams_members_removed: The list of TeamsChannelAccount objects representing the members removed from the conversation. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ - await self.on_members_removed_activity(teams_members_removed, turn_context) + return async def on_teams_channel_created( self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext @@ -724,6 +756,8 @@ async def on_teams_channel_created( """ Handles Teams channel created. + :param channel_info: The channel info object. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ @@ -735,6 +769,8 @@ async def on_teams_channel_deleted( """ Handles Teams channel deleted. + :param channel_info: The channel info object. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ @@ -746,6 +782,8 @@ async def on_teams_channel_renamed( """ Handles Teams channel renamed. + :param channel_info: The channel info object. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ @@ -757,6 +795,7 @@ async def on_teams_team_archived( """ Handles Teams team archived. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ @@ -768,6 +807,7 @@ async def on_teams_team_deleted( """ Handles Teams team deleted. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ @@ -779,6 +819,7 @@ async def on_teams_team_hard_deleted( """ Handles Teams team hard deleted. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ @@ -790,6 +831,8 @@ async def on_teams_channel_restored( """ Handles Teams channel restored. + :param channel_info: The channel info object. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ @@ -801,6 +844,7 @@ async def on_teams_team_renamed( """ Handles Teams team renamed. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ @@ -812,6 +856,7 @@ async def on_teams_team_restored( """ Handles Teams team restored. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ @@ -823,6 +868,7 @@ async def on_teams_team_unarchived( """ Handles Teams team unarchived. + :param team_info: The team info object. :param turn_context: The context object for the turn. :return: None """ @@ -837,21 +883,42 @@ async def on_event_activity(self, turn_context: TurnContext) -> None: """ if turn_context.activity.channel_id == "msteams": if turn_context.activity.name == "application/vnd.microsoft.readReceipt": - return await self.on_teams_read_receipt(turn_context) + return await self.on_teams_read_receipt( + ReadReceiptInfo.model_validate(turn_context.activity.value), + turn_context, + ) elif turn_context.activity.name == "application/vnd.microsoft.meetingStart": - return await self.on_teams_meeting_start(turn_context) + return await self.on_teams_meeting_start( + MeetingStartEventDetails.model_validate( + turn_context.activity.value + ), + turn_context, + ) elif turn_context.activity.name == "application/vnd.microsoft.meetingEnd": - return await self.on_teams_meeting_end(turn_context) + return await self.on_teams_meeting_end( + MeetingEndEventDetails.model_validate(turn_context.activity.value), + turn_context, + ) elif ( turn_context.activity.name == "application/vnd.microsoft.meetingParticipantJoin" ): - return await self.on_teams_meeting_participants_join(turn_context) + return await self.on_teams_meeting_participants_join( + MeetingParticipantsEventDetails.model_validate( + turn_context.activity.value + ), + turn_context, + ) elif ( turn_context.activity.name == "application/vnd.microsoft.meetingParticipantLeave" ): - return await self.on_teams_meeting_participants_leave(turn_context) + return await self.on_teams_meeting_participants_leave( + MeetingParticipantsEventDetails.model_validate( + turn_context.activity.value + ), + turn_context, + ) return await super().on_event_activity(turn_context) @@ -861,6 +928,7 @@ async def on_teams_meeting_start( """ Handles Teams meeting start. + :param meeting: The meeting start event details. :param turn_context: The context object for the turn. :return: None """ @@ -872,6 +940,7 @@ async def on_teams_meeting_end( """ Handles Teams meeting end. + :param meeting: The meeting end event details. :param turn_context: The context object for the turn. :return: None """ @@ -883,6 +952,7 @@ async def on_teams_read_receipt( """ Handles Teams read receipt. + :param read_receipt: The read receipt info. :param turn_context: The context object for the turn. :return: None """ @@ -894,6 +964,7 @@ async def on_teams_meeting_participants_join( """ Handles Teams meeting participants join. + :param meeting: The meeting participants event details. :param turn_context: The context object for the turn. :return: None """ @@ -905,6 +976,7 @@ async def on_teams_meeting_participants_leave( """ Handles Teams meeting participants leave. + :param meeting: The meeting participants event details. :param turn_context: The context object for the turn. :return: None """