Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@


class RouteHandler(Protocol[StateT]):
def __call__(self, context: TurnContext, state: StateT) -> Awaitable[None]: ...
def __call__(self, context: TurnContext, state: StateT, /) -> Awaitable[None]: ...
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ class AgentApplication(Agent, Generic[StateT]):
_adapter: Optional[ChannelServiceAdapter] = None
_auth: Optional[Authorization] = None
_proactive: Optional[Proactive] = None
_internal_before_turn: list[Callable[[TurnContext, StateT], Awaitable[bool]]] = []
_internal_after_turn: list[Callable[[TurnContext, StateT], Awaitable[bool]]] = []
_route_list: _RouteList[StateT] = _RouteList[StateT]()
_internal_before_turn: list[Callable[[TurnContext, StateT], Awaitable[bool]]]
_internal_after_turn: list[Callable[[TurnContext, StateT], Awaitable[bool]]]
_route_list: _RouteList[StateT]
_error: Optional[Callable[[TurnContext, Exception], Awaitable[None]]] = None
_turn_state_factory: Optional[Callable[[TurnContext], StateT]] = None

Expand All @@ -98,6 +98,8 @@ def __init__(
:type kwargs: Any
"""
self._route_list = _RouteList[StateT]()
self._internal_before_turn = []
self._internal_after_turn = []

configuration = kwargs

Expand Down Expand Up @@ -159,6 +161,15 @@ def __init__(
if authorization:
self._auth = authorization
else:
if not connection_manager:
logger.error(
"AgentApplication: connection_manager is required for Authorization.",
stack_info=True,
)
raise ApplicationError(
"The `AgentApplication` requires a `connection_manager` to initialize the `Authorization` instance."
)
Comment on lines +164 to +171

Comment thread
rodrigobr-msft marked this conversation as resolved.
auth_options = {
key: value
for key, value in configuration.items()
Comment on lines 173 to 175
Expand Down Expand Up @@ -244,6 +255,34 @@ def proactive(self) -> Proactive:
""")
return self._proactive

def before_turn(
self, handler: Callable[[TurnContext, StateT], Awaitable[bool]]
) -> Callable[[TurnContext, StateT], Awaitable[bool]]:
"""
Adds a handler to be called before each turn of the conversation.

:param handler: A function that takes a TurnContext and a StateT and returns an Awaitable.
:type handler: Callable[[TurnContext, StateT], Awaitable[bool]]
:return: The added handler.
:rtype: Callable[[TurnContext, StateT], Awaitable[bool]]
"""
Comment on lines +261 to +268
self._internal_before_turn.append(handler)
return handler

def after_turn(
self, handler: Callable[[TurnContext, StateT], Awaitable[bool]]
) -> Callable[[TurnContext, StateT], Awaitable[bool]]:
"""
Adds a handler to be called after each turn of the conversation.

:param handler: A function that takes a TurnContext and a StateT and returns an Awaitable.
:type handler: Callable[[TurnContext, StateT], Awaitable[bool]]
:return: The added handler.
:rtype: Callable[[TurnContext, StateT], Awaitable[bool]]
"""
Comment on lines +275 to +282
self._internal_after_turn.append(handler)
return handler

def add_route(
self,
selector: RouteSelector,
Expand All @@ -259,7 +298,7 @@ def add_route(

:param selector: A function that takes a TurnContext and returns a boolean indicating whether the route should be selected.
:type selector: Callable[[:class:`microsoft_agents.hosting.core.turn_context.TurnContext`], bool]
:param handler: A function that takes a TurnContext and a TurnState and returns an Awaitable.
:param handler: A function that takes a TurnContext and a StateT and returns an Awaitable.
:type handler: :class:`microsoft_agents.hosting.core.app._type_defs.RouteHandler`[StateT]
:param is_invoke: Whether the route is for an invoke activity, defaults to False
:type is_invoke: bool, Optional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
Licensed under the MIT License.
"""

from datetime import datetime
import logging
from typing import TypeVar, Optional, Callable, Awaitable, Generic, cast
import jwt
from typing import Optional, Callable, Awaitable, cast

from microsoft_agents.activity import Activity, Channels, SignInConstants, TokenResponse
from microsoft_agents.activity.activity_types import ActivityTypes
Expand Down Expand Up @@ -126,6 +124,18 @@ def _init_handlers(self) -> None:
auth_handler=auth_handler,
)

@property
def connection_manager(self) -> Connections:
"""
The connection manager for the authorization instance.

The connection manager is responsible for managing the connections to the various authentication providers.

:return: The connection manager.
:rtype: :class:`microsoft_agents.hosting.core.authorization.Connections`
"""
Comment thread
Copilot marked this conversation as resolved.
return self._connection_manager

@staticmethod
def _sign_in_state_key(context: TurnContext) -> str:
"""Generate a unique storage key for the sign-in state based on the context.
Expand Down
4 changes: 4 additions & 0 deletions tests/hosting_core/app/_oauth/test_authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ def test_resolve_handler(self, connection_manager, storage, auth_handler_id):
auth_handler_id, **handler_config
)

def test_connection_manager_property(self, connection_manager, storage):
auth = Authorization(storage, connection_manager, **ENV_DICT)
assert auth.connection_manager is connection_manager

def test_sign_in_state_key(self, mocker, connection_manager, storage):
auth = Authorization(storage, connection_manager, **ENV_DICT)
context = self.TurnContext(mocker)
Expand Down
Loading
Loading