diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/conversation_parameters.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/conversation_parameters.py index 747e7814..0c06ef11 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/conversation_parameters.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/conversation_parameters.py @@ -7,6 +7,7 @@ from .activity import Activity from .agents_model import AgentsModel from ._type_aliases import NonEmptyString +from .conversation_account import ConversationAccount class ConversationParameters(AgentsModel): @@ -29,6 +30,8 @@ class ConversationParameters(AgentsModel): :type channel_data: object :param tenant_id: (Optional) The tenant ID in which the conversation should be created :type tenant_id: str + :param conversation: (Optional) The conversation account to use when creating the new conversation + :type conversation: ~microsoft_agents.activity.ConversationAccount """ is_group: bool = None @@ -38,3 +41,4 @@ class ConversationParameters(AgentsModel): activity: Activity = None channel_data: object = None tenant_id: NonEmptyString = None + conversation: ConversationAccount = None diff --git a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/authorization.py b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/authorization.py index 51cc75bc..bd40288b 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/authorization.py +++ b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/authorization.py @@ -7,7 +7,13 @@ from typing import Optional, Callable, Awaitable, cast from dataclasses import dataclass -from microsoft_agents.activity import Activity, Channels, SignInConstants, TokenResponse +from microsoft_agents.activity import ( + Activity, + Channels, + ChannelId, + SignInConstants, + TokenResponse, +) from microsoft_agents.activity.activity_types import ActivityTypes from ...turn_context import TurnContext @@ -283,7 +289,8 @@ async def _start_or_continue_sign_in( elif sign_in_response.tag in [_FlowStateTag.BEGIN, _FlowStateTag.CONTINUE]: # Handling special case for Teams SSO, ConsentRequired if not ( - context.activity.channel_id.channel == Channels.ms_teams + ChannelId.get_channel(context.activity.channel_id) + == Channels.ms_teams.value and sign_in_state.continuation_activity and context.activity.type == ActivityTypes.invoke and context.activity.name diff --git a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/proactive/conversation.py b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/proactive/conversation.py index aadc876a..079136dc 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/proactive/conversation.py +++ b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/proactive/conversation.py @@ -5,7 +5,7 @@ from __future__ import annotations -from typing import Optional, TYPE_CHECKING +from typing import TYPE_CHECKING from microsoft_agents.activity import ConversationReference from microsoft_agents.hosting.core.authorization import ClaimsIdentity @@ -39,7 +39,7 @@ class Conversation(StoreItem): def __init__( self, - claims: "dict[str, str] | ClaimsIdentity", + claims: dict[str, str] | ClaimsIdentity, conversation_reference: ConversationReference, ) -> None: if isinstance(claims, ClaimsIdentity): @@ -55,7 +55,7 @@ def __init__( # ------------------------------------------------------------------ @classmethod - def from_turn_context(cls, context: "TurnContext") -> "Conversation": + def from_turn_context(cls, context: TurnContext) -> Conversation: """ Create a :class:`microsoft_agents.hosting.core.app.proactive.Conversation` from the current turn context. @@ -65,11 +65,7 @@ def from_turn_context(cls, context: "TurnContext") -> "Conversation": and conversation reference. :rtype: :class:`microsoft_agents.hosting.core.app.proactive.Conversation` """ - from microsoft_agents.hosting.core.channel_adapter import ChannelAdapter - - identity: Optional[ClaimsIdentity] = context.turn_state.get( - ChannelAdapter.AGENT_IDENTITY_KEY - ) + identity: ClaimsIdentity | None = context.identity reference = context.activity.get_conversation_reference() return cls(identity or {}, reference) @@ -78,7 +74,7 @@ def from_turn_context(cls, context: "TurnContext") -> "Conversation": # ------------------------------------------------------------------ @staticmethod - def claims_from_identity(identity: ClaimsIdentity) -> "dict[str, str]": + def claims_from_identity(identity: ClaimsIdentity) -> dict[str, str]: """ Return the subset of claims from *identity* that are relevant for proactive messaging (``aud``, ``azp``, ``appid``, ``idtyp``, ``ver``, ``iss``, ``tid``). @@ -91,7 +87,7 @@ def claims_from_identity(identity: ClaimsIdentity) -> "dict[str, str]": return {k: v for k, v in identity.claims.items() if k in _PERSISTED_CLAIM_KEYS} @staticmethod - def identity_from_claims(claims: "dict[str, str]") -> ClaimsIdentity: + def identity_from_claims(claims: dict[str, str]) -> ClaimsIdentity: """ Reconstruct a :class:`~microsoft_agents.hosting.core.authorization.ClaimsIdentity` from a previously persisted claims dict. @@ -142,7 +138,7 @@ def store_item_to_json(self) -> dict: } @staticmethod - def from_json_to_store_item(json_data: dict) -> "Conversation": + def from_json_to_store_item(json_data: dict) -> Conversation: reference = ConversationReference.model_validate( json_data.get("conversation_reference", {}) ) diff --git a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/channel_adapter.py b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/channel_adapter.py index 7d00fc3a..8695b7ab 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/channel_adapter.py +++ b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/channel_adapter.py @@ -1,6 +1,8 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. +from __future__ import annotations + from abc import ABC, abstractmethod from collections.abc import Callable from typing import Awaitable @@ -8,6 +10,7 @@ from microsoft_agents.activity import ChannelAdapterProtocol from microsoft_agents.activity import ( Activity, + ChannelId, ConversationAccount, ConversationReference, ConversationParameters, @@ -15,7 +18,7 @@ ) from .turn_context import TurnContext -from .middleware_set import MiddlewareSet +from .middleware_set import MiddlewareSet, Middleware class ChannelAdapter(ABC, ChannelAdapterProtocol): @@ -78,7 +81,7 @@ async def delete_activity( """ raise NotImplementedError() - def use(self, middleware): + def use(self, middleware: Middleware) -> ChannelAdapter: """ Registers a middleware handler with the adapter. @@ -202,11 +205,11 @@ async def create_conversation( # Create a conversation update activity conversation_update = Activity( - type=ActivityTypes.CONVERSATION_UPDATE, - channel_id=channel_id, + type=ActivityTypes.conversation_update, + channel_id=ChannelId(channel_id), service_url=service_url, conversation=conversation_parameters.conversation, - recipient=conversation_parameters.bot, + recipient=conversation_parameters.agent, from_property=conversation_parameters.members[0], members_added=conversation_parameters.members, ) diff --git a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/channel_service_adapter.py b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/channel_service_adapter.py index 1cda31b5..64e3a704 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/channel_service_adapter.py +++ b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/channel_service_adapter.py @@ -4,9 +4,8 @@ from __future__ import annotations from abc import ABC -from copy import Error from http import HTTPStatus -from typing import Awaitable, Callable, cast, Optional +from typing import Awaitable, Callable, cast from uuid import uuid4 from microsoft_agents.activity import ( @@ -65,16 +64,10 @@ async def send_activities( :type activities: list[:class:`microsoft_agents.activity.Activity`] :return: List of resource responses for the sent activities. :rtype: list[:class:`microsoft_agents.activity.ResourceResponse`] - :raises TypeError: If context or activities are None/invalid. + :raises ValueError: If the activities list is empty. """ - if not context: - raise TypeError("Expected TurnContext but got None instead") - - if activities is None: - raise TypeError("Expected Activities list but got None instead") - if len(activities) == 0: - raise TypeError("Expecting one or more activities, but the list was empty.") + raise ValueError("send_activities: activities list cannot be empty") responses = [] @@ -97,7 +90,9 @@ async def send_activities( context.turn_state.get(self._AGENT_CONNECTOR_CLIENT_KEY), ) if not connector_client: - raise Error("Unable to extract ConnectorClient from turn context.") + raise RuntimeError( + "Unable to extract ConnectorClient from turn context." + ) with spans.AdapterSendActivities([activity]): if activity.reply_to_id: @@ -131,13 +126,11 @@ async def update_activity(self, context: TurnContext, activity: Activity): :type activity: :class:`microsoft_agents.activity.Activity` :return: Resource response for the updated activity. :rtype: :class:`microsoft_agents.activity.ResourceResponse` - :raises TypeError: If context or activity are None/invalid. + :raises TypeError: activity.id is None """ - if not context: - raise TypeError("Expected TurnContext but got None instead") - if activity is None: - raise TypeError("Expected Activity but got None instead") + if activity.id is None: + raise TypeError("Expected Activity with an id but got None instead") with spans.AdapterUpdateActivity(activity): @@ -146,7 +139,9 @@ async def update_activity(self, context: TurnContext, activity: Activity): context.turn_state.get(self._AGENT_CONNECTOR_CLIENT_KEY), ) if not connector_client: - raise Error("Unable to extract ConnectorClient from turn context.") + raise RuntimeError( + "Unable to extract ConnectorClient from turn context." + ) return await connector_client.conversations.update_activity( activity.conversation.id, activity.id, activity @@ -162,13 +157,12 @@ async def delete_activity( :type context: :class:`microsoft_agents.hosting.core.turn_context.TurnContext` :param reference: Reference to the conversation and activity to delete. :type reference: :class:`microsoft_agents.activity.ConversationReference` - :raises TypeError: If context or reference are None/invalid. + :raises TypeError: reference.conversation or reference.activity_id is None """ - if not context: - raise TypeError("Expected TurnContext but got None instead") - - if not reference: - raise TypeError("Expected ConversationReference but got None instead") + if not reference.conversation or not reference.activity_id: + raise TypeError( + "Expected ConversationReference with conversation and activity_id but got None instead" + ) with spans.AdapterDeleteActivity(context.activity): @@ -177,7 +171,9 @@ async def delete_activity( context.turn_state.get(self._AGENT_CONNECTOR_CLIENT_KEY), ) if not connector_client: - raise Error("Unable to extract ConnectorClient from turn context.") + raise RuntimeError( + "Unable to extract ConnectorClient from turn context." + ) await connector_client.conversations.delete_activity( reference.conversation.id, reference.activity_id @@ -238,7 +234,7 @@ async def continue_conversation_with_claims( :param callback: The method to call for the resulting agent turn. :type callback: Callable[[:class:`microsoft_agents.hosting.core.turn_context.TurnContext`], Awaitable] :param audience: The audience for the conversation. - :type audience: Optional[str] + :type audience: str | None """ with spans.AdapterContinueConversation(continuation_activity): return await self.process_proactive( @@ -261,12 +257,6 @@ async def create_conversation( # pylint: disable=arguments-differ raise TypeError( "CloudAdapter.create_conversation(): service_url is required." ) - if not conversation_parameters: - raise TypeError( - "CloudAdapter.create_conversation(): conversation_parameters is required." - ) - if not callback: - raise TypeError("CloudAdapter.create_conversation(): callback is required.") # Create a ClaimsIdentity, to create the connector and for adding to the turn context. claims_identity = self.create_claims_identity(agent_app_id) @@ -369,7 +359,7 @@ async def process_activity( claims_identity: ClaimsIdentity, activity: Activity, callback: Callable[[TurnContext], Awaitable], - ): + ) -> InvokeResponse | None: """ Creates a turn context and runs the middleware pipeline for an incoming activity. @@ -381,7 +371,7 @@ async def process_activity( :type callback: Callable[[:class:`microsoft_agents.hosting.core.turn_context.TurnContext`], Awaitable] :return: A task that represents the work queued to execute. - :rtype: Optional[:class:`microsoft_agents.activity.InvokeResponse`] + :rtype: :class:`microsoft_agents.activity.InvokeResponse` | None .. note:: This class processes an activity received by the agents web server. This includes any messages @@ -424,7 +414,7 @@ async def process_activity( context.turn_state[self.USER_TOKEN_CLIENT_KEY] = user_token_client # Create the connector client to use for outbound requests. - connector_client: Optional[ConnectorClient] = None + connector_client: ConnectorClient | None = None if self._resolve_if_connector_client_is_needed(activity): connector_client = ( await self._channel_service_client_factory.create_connector_client( @@ -466,8 +456,6 @@ def create_claims_identity(self, agent_app_id: str = "") -> ClaimsIdentity: @staticmethod def _validate_continuation_activity(continuation_activity: Activity): - if not continuation_activity: - raise TypeError("CloudAdapter: continuation_activity is required.") if not continuation_activity.conversation: raise TypeError( @@ -506,7 +494,7 @@ def _create_turn_context( claims_identity: ClaimsIdentity, oauth_scope: str, callback: Callable[[TurnContext], Awaitable], - activity: Optional[Activity] = None, + activity: Activity | None = None, ) -> TurnContext: context = TurnContext(self, activity, claims_identity) @@ -519,13 +507,13 @@ def _create_turn_context( return context - def _process_turn_results(self, context: TurnContext) -> Optional[InvokeResponse]: + def _process_turn_results(self, context: TurnContext) -> InvokeResponse | None: """Process the results of a turn and return the appropriate response. :param context: The turn context :type context: :class:`microsoft_agents.hosting.core.turn_context.TurnContext` :return: The invoke response, if applicable - :rtype: Optional[:class:`microsoft_agents.activity.InvokeResponse`] + :rtype: :class:`microsoft_agents.activity.InvokeResponse` | None """ # Handle ExpectedReplies scenarios where all activities have been # buffered and sent back at once in an invoke response. @@ -542,11 +530,11 @@ def _process_turn_results(self, context: TurnContext) -> Optional[InvokeResponse if context.activity.type == ActivityTypes.invoke: with spans.AdapterSendActivities([context.activity]): - activity_invoke_response: Activity = context.turn_state.get( - self.INVOKE_RESPONSE_KEY + activity_invoke_response: Activity | None = cast( + Activity | None, context.turn_state.get(self.INVOKE_RESPONSE_KEY) ) if not activity_invoke_response: - return InvokeResponse(status=HTTPStatus.OK) + return InvokeResponse(status=HTTPStatus.NOT_IMPLEMENTED) return InvokeResponse.model_validate(activity_invoke_response.value) diff --git a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/client/channel_host_protocol.py b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/client/channel_host_protocol.py index a2990357..9227a117 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/client/channel_host_protocol.py +++ b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/client/channel_host_protocol.py @@ -8,6 +8,11 @@ class ChannelHostProtocol(Protocol): + + host_endpoint: str + host_app_id: str + channels: dict[str, ChannelInfoProtocol] + def __init__( self, host_endpoint: str, diff --git a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/client/channel_protocol.py b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/client/channel_protocol.py index a5855af0..c045b3d0 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/client/channel_protocol.py +++ b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/client/channel_protocol.py @@ -16,7 +16,7 @@ async def post_activity( conversation_id: str, activity: Activity, *, - response_body_type: type[AgentsModel] = None, + response_body_type: type[AgentsModel] | None = None, **kwargs, ) -> InvokeResponse: raise NotImplementedError() diff --git a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/http/_http_adapter_base.py b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/http/_http_adapter_base.py index ca84c0c2..869137fe 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/http/_http_adapter_base.py +++ b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/http/_http_adapter_base.py @@ -5,6 +5,7 @@ from abc import ABC from traceback import format_exc +from http import HTTPStatus from microsoft_agents.activity import Activity, DeliveryModes from microsoft_agents.hosting.core.authorization import ClaimsIdentity, Connections @@ -134,8 +135,12 @@ async def process_request( ): with spans.AdapterWriteResponse(activity): # Invoke and ExpectReplies cannot be performed async + invoke_response_status = ( + invoke_response.status if invoke_response else None + ) return HttpResponseFactory.json( - invoke_response.body, invoke_response.status + invoke_response.body if invoke_response else None, + invoke_response_status or HTTPStatus.NOT_IMPLEMENTED, ) return HttpResponseFactory.accepted() diff --git a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/message_factory.py b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/message_factory.py index 91a55730..987f6818 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/message_factory.py +++ b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/message_factory.py @@ -88,9 +88,11 @@ def suggested_actions( :param input_hint: :return: """ - actions = SuggestedActions(actions=actions) + suggested_actions = SuggestedActions(actions=actions) message = Activity( - type=ActivityTypes.message, input_hint=input_hint, suggested_actions=actions + type=ActivityTypes.message, + input_hint=input_hint, + suggested_actions=suggested_actions, ) if text: message.text = text @@ -122,16 +124,14 @@ def attachment( :param input_hint: :return: """ - return attachment_activity( - AttachmentLayoutTypes.list, [attachment], text, speak, input_hint - ) + return MessageFactory.list([attachment], text, speak, input_hint) @staticmethod def list( attachments: list[Attachment], text: str | None = None, speak: str | None = None, - input_hint: InputHints | str = None, + input_hint: InputHints | str | None = None, ) -> Activity: """ Returns a message that will display a set of attachments in list form. @@ -154,6 +154,10 @@ def list( :param input_hint: :return: """ + if not input_hint: + return attachment_activity( + AttachmentLayoutTypes.list, attachments, text, speak + ) return attachment_activity( AttachmentLayoutTypes.list, attachments, text, speak, input_hint ) @@ -163,7 +167,7 @@ def carousel( attachments: list[Attachment], text: str | None = None, speak: str | None = None, - input_hint: InputHints | str = None, + input_hint: InputHints | str | None = None, ) -> Activity: """ Returns a message that will display a set of attachments using a carousel layout. @@ -186,6 +190,10 @@ def carousel( :param input_hint: :return: """ + if not input_hint: + return attachment_activity( + AttachmentLayoutTypes.carousel, attachments, text, speak + ) return attachment_activity( AttachmentLayoutTypes.carousel, attachments, text, speak, input_hint ) @@ -218,6 +226,4 @@ def content_url( attachment = Attachment(content_type=content_type, content_url=url) if name: attachment.name = name - return attachment_activity( - AttachmentLayoutTypes.list, [attachment], text, speak, input_hint - ) + return MessageFactory.attachment(attachment, text, speak, input_hint) diff --git a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/rest_channel_service_client_factory.py b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/rest_channel_service_client_factory.py index 19640539..ab265cf1 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/rest_channel_service_client_factory.py +++ b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/rest_channel_service_client_factory.py @@ -63,16 +63,20 @@ async def _get_agentic_token(self, context: TurnContext, service_url: str) -> st if not agent_instance_id: raise ValueError("Agent instance ID is required for agentic identity role") + tenant_id = context.activity.get_agentic_tenant_id() + if not tenant_id: + raise ValueError("Agentic tenant ID is required for agentic activities") + if context.activity.recipient.role == RoleTypes.agentic_identity: token, _ = await connection.get_agentic_instance_token( - context.activity.get_agentic_tenant_id(), agent_instance_id + tenant_id, agent_instance_id ) else: agentic_user = context.activity.get_agentic_user() if not agentic_user: raise ValueError("Agentic user is required for agentic user role") token = await connection.get_agentic_user_token( - context.activity.get_agentic_tenant_id(), + tenant_id, agent_instance_id, agentic_user, [AuthenticationConstants.APX_PRODUCTION_SCOPE], @@ -91,8 +95,6 @@ async def create_connector_client( scopes: list[str] | None = None, use_anonymous: bool = False, ) -> ConnectorClientBase: - if not claims_identity: - raise TypeError("claims_identity is required") if not service_url: raise TypeError( "RestChannelServiceClientFactory.create_connector_client: service_url can't be None or Empty" @@ -152,10 +154,8 @@ async def create_user_token_client( :param claims_identity: The ClaimsIdentity of the user. :param use_anonymous: Whether to use an anonymous token provider. """ - if not context or not claims_identity: - raise ValueError("context and claims_identity are required") - scopes = claims_identity.get_token_scope() if claims_identity else None + scopes = claims_identity.get_token_scope() with spans.AdapterCreateUserTokenClient( token_service_endpoint=self._token_service_endpoint, diff --git a/tests/hosting_core/app/proactive/test_conversation.py b/tests/hosting_core/app/proactive/test_conversation.py index 3c65f168..8677ddf0 100644 --- a/tests/hosting_core/app/proactive/test_conversation.py +++ b/tests/hosting_core/app/proactive/test_conversation.py @@ -9,7 +9,6 @@ from microsoft_agents.activity import ConversationAccount, ConversationReference from microsoft_agents.hosting.core.app.proactive import Conversation from microsoft_agents.hosting.core.authorization import ClaimsIdentity -from microsoft_agents.hosting.core.channel_adapter import ChannelAdapter def _make_reference( @@ -75,7 +74,7 @@ def test_from_turn_context_extracts_reference_and_identity(self): ctx = MagicMock() ctx.activity.get_conversation_reference.return_value = ref - ctx.turn_state = {ChannelAdapter.AGENT_IDENTITY_KEY: identity} + ctx.identity = identity conv = Conversation.from_turn_context(ctx) diff --git a/tests/hosting_core/app/proactive/test_proactive.py b/tests/hosting_core/app/proactive/test_proactive.py index d7c73f51..e41c1038 100644 --- a/tests/hosting_core/app/proactive/test_proactive.py +++ b/tests/hosting_core/app/proactive/test_proactive.py @@ -24,7 +24,6 @@ ProactiveOptions, ) from microsoft_agents.hosting.core.authorization import ClaimsIdentity -from microsoft_agents.hosting.core.channel_adapter import ChannelAdapter # --------------------------------------------------------------------------- # Helpers @@ -165,7 +164,7 @@ async def test_store_from_turn_context(self, proactive): ctx = MagicMock(spec=TurnContext) ctx.activity = MagicMock() ctx.activity.get_conversation_reference.return_value = ref - ctx.turn_state = {ChannelAdapter.AGENT_IDENTITY_KEY: identity} + ctx.identity = identity await proactive.store_conversation(ctx) result = await proactive.get_conversation("ctx-conv") diff --git a/tests/hosting_core/test_rest_channel_service_client_factory.py b/tests/hosting_core/test_rest_channel_service_client_factory.py index 22db417e..0f387cdb 100644 --- a/tests/hosting_core/test_rest_channel_service_client_factory.py +++ b/tests/hosting_core/test_rest_channel_service_client_factory.py @@ -51,6 +51,7 @@ def activity_agentic_user(self): id="bot1", agentic_app_id="agentic_app_id", agentic_user_id="agentic_user_id", + tenant_id="tenant_id", role=RoleTypes.agentic_user, ), service_url="https://service.url/", @@ -69,6 +70,7 @@ def activity_agentic_identity(self): recipient=ChannelAccount( id="bot1", agentic_app_id="agentic_app_id", + tenant_id="tenant_id", role=RoleTypes.agentic_identity, ), service_url="https://service.url/", @@ -325,7 +327,7 @@ async def test_create_connector_client_agentic_identity( ) assert token_provider.get_agentic_instance_token.call_count == 1 token_provider.get_agentic_instance_token.assert_called_once_with( - None, "agentic_app_id" + "tenant_id", "agentic_app_id" ) TeamsConnectorClient.__new__.assert_called_once_with( TeamsConnectorClient, endpoint=DEFAULTS.service_url, token=DEFAULTS.token @@ -376,7 +378,7 @@ async def test_create_connector_client_agentic_identity_non_msal_provider( # verify the alternate blueprint redirect happened via ``configuration`` connection_manager.get_connection.assert_called_once_with("alt_blueprint_id") token_provider.get_agentic_instance_token.assert_called_once_with( - None, "agentic_app_id" + "tenant_id", "agentic_app_id" ) @pytest.mark.asyncio @@ -420,7 +422,7 @@ async def test_create_connector_client_agentic_no_configuration( # verify: no redirect attempted, token still acquired connection_manager.get_connection.assert_not_called() token_provider.get_agentic_instance_token.assert_called_once_with( - None, "agentic_app_id" + "tenant_id", "agentic_app_id" ) @pytest.mark.parametrize("alt_blueprint", [True, False]) @@ -481,7 +483,7 @@ async def test_create_connector_client_agentic_user( ) assert token_provider.get_agentic_user_token.call_count == 1 token_provider.get_agentic_user_token.assert_called_once_with( - None, + "tenant_id", "agentic_app_id", "agentic_user_id", [AuthenticationConstants.APX_PRODUCTION_SCOPE],