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 @@ -76,6 +76,7 @@ class AgentApplication(Agent, Generic[StateT]):
_route_list: _RouteList[StateT]
_error: Optional[Callable[[TurnContext, Exception], Awaitable[None]]] = None
_turn_state_factory: Optional[Callable[[TurnContext], StateT]] = None
_connection_manager: Connections

def __init__(
self,
Expand Down Expand Up @@ -159,7 +160,15 @@ def __init__(

# TODO: decide how to initialize the Authorization (params vs options vs kwargs)
if authorization:
if connection_manager:
logger.error(
"AgentApplication: connection_manager is not needed when authorization is provided."
)
Comment thread
rodrigobr-msft marked this conversation as resolved.
raise ApplicationError(
"The `AgentApplication` does not take a `connection_manager` when `authorization` is provided."
)
self._auth = authorization
self._connection_manager = self._auth.connection_manager
else:
if not connection_manager:
logger.error(
Expand All @@ -178,9 +187,20 @@ def __init__(
self._auth = Authorization(
storage=self._options.storage,
connection_manager=connection_manager,
handlers=options.authorization_handlers,
auth_handlers=options.authorization_handlers,
**auth_options,
)
self._connection_manager = connection_manager

@property
def connection_manager(self) -> Connections:
"""
The application's connection manager.

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

@property
def adapter(self) -> ChannelServiceAdapter:
Expand Down
47 changes: 47 additions & 0 deletions tests/hosting_core/app/test_agent_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,3 +433,50 @@ async def on_event(ctx, state):
await app.on_turn(StubTurnContext(_make_event_activity()))

assert calls == ["event", "after"]


# ---------------------------------------------------------------------------
# connection_manager property and constructor guard
# ---------------------------------------------------------------------------


def test_init_raises_when_both_authorization_and_connection_manager_provided():
"""Providing both authorization and connection_manager is ambiguous and should raise."""
with pytest.raises(ApplicationError):
AgentApplication[TurnState](
options=ApplicationOptions(storage=MemoryStorage()),
authorization=make_auth(),
connection_manager=_ConnectionManager(),
)


def test_connection_manager_property_returns_manager_from_authorization():
"""When authorization is provided, connection_manager property reflects auth's manager."""
cm = _ConnectionManager()
auth = Authorization(storage=MemoryStorage(), connection_manager=cm)
app = AgentApplication[TurnState](
options=ApplicationOptions(storage=MemoryStorage()),
authorization=auth,
)
assert app.connection_manager is cm


def test_connection_manager_property_returns_directly_passed_manager():
"""When connection_manager kwarg is used (no authorization), the property returns it."""
cm = _ConnectionManager()
app = AgentApplication[TurnState](
options=ApplicationOptions(storage=MemoryStorage()),
connection_manager=cm,
)
assert app.connection_manager is cm


def test_init_with_connection_manager_only_creates_auth():
"""Passing only connection_manager should auto-create an Authorization instance."""
cm = _ConnectionManager()
app = AgentApplication[TurnState](
options=ApplicationOptions(storage=MemoryStorage()),
connection_manager=cm,
)
assert app.auth is not None
assert app.connection_manager is cm
Loading