Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
ca07a83
Drafting extension starter sample
rodrigobr-msft Sep 18, 2025
1f85836
Completed basic outline
rodrigobr-msft Sep 18, 2025
00839d3
doc_samples directory created
rodrigobr-msft Sep 18, 2025
37e7f70
Enhancing app routing
rodrigobr-msft Sep 18, 2025
14de9d5
Cleaned up new route logic and its usage in the extension-starter sample
rodrigobr-msft Sep 18, 2025
ba30c82
Implement asynchronous token retrieval methods in AgenticMsalAuth class
rodrigobr-msft Sep 23, 2025
755e973
get_agentic_user_token implementation
rodrigobr-msft Sep 23, 2025
c79d56b
get_agentic_user_token simplified implementation with ConfidentialCli…
rodrigobr-msft Sep 23, 2025
c671841
Enhance AgenticMsalAuth: update get_agentic_instance_token to return …
rodrigobr-msft Sep 23, 2025
1fed41f
Merge branch 'main' of https://github.com/microsoft/Agents-for-python…
rodrigobr-msft Sep 24, 2025
c4a8381
Adding improved route handling tests
rodrigobr-msft Sep 24, 2025
5568b6e
Adding RouteList tests
rodrigobr-msft Sep 24, 2025
b57b7bf
Adding __iter__ to RouteList and fixing AgentApplication usage of Rou…
rodrigobr-msft Sep 24, 2025
b06af40
Supporting authorization variants
rodrigobr-msft Sep 24, 2025
4ce735e
Continued auth refactor
rodrigobr-msft Sep 25, 2025
ac48fbc
Addressing continuation activity
rodrigobr-msft Sep 25, 2025
a078bd6
Adding authorization tests
rodrigobr-msft Sep 25, 2025
860fade
Passing Authorization tests
rodrigobr-msft Sep 25, 2025
56d46b8
Basic AgenticAuthorization tests
rodrigobr-msft Sep 25, 2025
e514ea8
Added AgenticAuthorization tests
rodrigobr-msft Sep 25, 2025
83c6688
Finalized fundamental unit tests for agentic auth scenarios
rodrigobr-msft Sep 25, 2025
23efb16
Extension starter sample
rodrigobr-msft Sep 25, 2025
193508d
agentic_selector decorator
rodrigobr-msft Sep 26, 2025
537b5c8
Route helpers
rodrigobr-msft Sep 26, 2025
2656435
Formatting
rodrigobr-msft Sep 26, 2025
ef01438
Formatting
rodrigobr-msft Sep 26, 2025
185acfc
Address review comments and more breaking changes
rodrigobr-msft Sep 26, 2025
770cf69
Shifting around exchange token logic
rodrigobr-msft Sep 27, 2025
389b6cd
Adding dynamic loading of connection and related tests
rodrigobr-msft Sep 27, 2025
8a41020
Aligning authorization handlers with how .NET does it
rodrigobr-msft Sep 27, 2025
a0df177
get_token_provider implemented and tested
rodrigobr-msft Sep 29, 2025
ea54c51
Tested UserAuthorization and AgenticUserAuthorization classes
rodrigobr-msft Sep 29, 2025
84edf3a
Finalized refactor tests
rodrigobr-msft Sep 29, 2025
82e4ae5
Sample compat
rodrigobr-msft Sep 29, 2025
6611ed8
Compat changes
rodrigobr-msft Sep 29, 2025
98436a8
Passing all tests again
rodrigobr-msft Sep 30, 2025
c3c3db3
Repurposing SignInState
rodrigobr-msft Sep 30, 2025
3d7a962
Completed tests for auth fix
rodrigobr-msft Sep 30, 2025
a34cdfb
Changes to avoid auth on typing
rodrigobr-msft Sep 30, 2025
3100fc0
Changes to avoid auth on typing
rodrigobr-msft Sep 30, 2025
04eaf7e
Enable passing TurnContext into create_connector_client
rodrigobr-msft Sep 30, 2025
86dfac2
Tweaks to work almost end-to-end / fixing connector client construction
rodrigobr-msft Oct 1, 2025
b564193
Moving agentic static methods to be instance methods of Activity and …
rodrigobr-msft Oct 1, 2025
f791827
Addressing PR review comments
rodrigobr-msft Oct 1, 2025
a82c1f7
Reformatting files with black
rodrigobr-msft Oct 1, 2025
511b9a8
Merge branch 'main' of https://github.com/microsoft/Agents-for-python…
rodrigobr-msft Oct 1, 2025
fe197cb
Fixing test case
rodrigobr-msft Oct 1, 2025
1f2ce31
Removing unneeded subchannel constants
rodrigobr-msft Oct 2, 2025
5f98c7b
Fixed merge conflict
rodrigobr-msft Oct 2, 2025
68db989
Tweaks to imports
rodrigobr-msft Oct 2, 2025
d8ebb19
Fixing test import
rodrigobr-msft Oct 2, 2025
cf1ac30
Fixed new merge conflicts
rodrigobr-msft Oct 2, 2025
fb4e583
Fixed improved route handling tests
rodrigobr-msft Oct 2, 2025
fe900ae
Adding to extension starter sample
rodrigobr-msft Oct 2, 2025
76d795e
Merge branch 'main' of https://github.com/microsoft/Agents-for-python…
rodrigobr-msft Oct 6, 2025
3b3ca1c
Reorganizing sample code
rodrigobr-msft Oct 6, 2025
02e173c
Change to add_route for RouteList
rodrigobr-msft Oct 6, 2025
c5ad7f8
Adding add_route docstring
rodrigobr-msft Oct 6, 2025
6162523
Fixing RouteList definition and iteration
rodrigobr-msft Oct 6, 2025
c75d904
Formatting src
rodrigobr-msft Oct 6, 2025
30bca99
Redoing sample decorator definitions to take in arguments
rodrigobr-msft Oct 6, 2025
c4a2989
Finalized extension sample
rodrigobr-msft Oct 6, 2025
c84871d
Fixed RouteList usage in AgentApplication
rodrigobr-msft Oct 6, 2025
2df8da9
Docstrings to code
rodrigobr-msft Oct 6, 2025
5b1de27
Added argument validation to add_route
rodrigobr-msft Oct 6, 2025
be72c69
Fixing RouteRank bounds, tests, and typos
rodrigobr-msft Oct 7, 2025
9e7fdfa
Adding copyright comment
rodrigobr-msft Oct 7, 2025
b6e5e9c
Merge branch 'main' of https://github.com/microsoft/Agents-for-python…
rodrigobr-msft Oct 7, 2025
5cdc2b7
Adding copyright header to hosting.core modules
rodrigobr-msft Oct 7, 2025
8892222
Removing strenum dependency
rodrigobr-msft Oct 7, 2025
abfb229
Removed debug printing
rodrigobr-msft Oct 7, 2025
62aca17
Removed todos
rodrigobr-msft Oct 7, 2025
b1d0383
Changing whitespace
rodrigobr-msft Oct 7, 2025
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
@@ -1,5 +1,4 @@
from typing import Annotated
from pydantic import StringConstraints


NonEmptyString = Annotated[str, StringConstraints(min_length=1)]
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,6 @@ def create_reply(self, text: str = None, locale: str = None):
def create_trace(
self, name: str, value: object = None, value_type: str = None, label: str = None
):
# robrandao: TODO -> needs to handle Nones like create_reply
"""
Creates a new trace activity based on this activity.

Expand Down Expand Up @@ -476,7 +475,6 @@ def create_trace(
def create_trace_activity(
name: str, value: object = None, value_type: str = None, label: str = None
):
# robrandao: TODO -> SkipNone
"""
Creates an instance of the :class:`Activity` class as a TraceActivity object.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from __future__ import annotations

import logging
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import re
from typing import Dict, List, Optional
from microsoft_agents.hosting.core import (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
from .turn_context import TurnContext

# Application Style
from .app._type_defs import RouteHandler, RouteSelector, StateT
from .app.agent_application import AgentApplication
from .app.app_error import ApplicationError
from .app.app_options import ApplicationOptions
from .app.input_file import InputFile, InputFileDownloader
from .app.query import Query
from .app.route import Route, RouteHandler
from .app._routes import _Route, _RouteList, RouteRank
from .app.typing_indicator import TypingIndicator

# App Auth
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from ._flow_state import _FlowState, _FlowStateTag, _FlowErrorTag
from ._flow_storage_client import _FlowStorageClient
from ._oauth_flow import _OAuthFlow, _FlowResponse
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from __future__ import annotations
from http import HTTPStatus
from pydantic import BaseModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
from .app_options import ApplicationOptions
from .input_file import InputFile, InputFileDownloader
from .query import Query
from .route import Route, RouteHandler
from ._routes import _RouteList, _Route, RouteRank
from .typing_indicator import TypingIndicator
from ._type_defs import RouteHandler, RouteSelector, StateT

# Auth
from .oauth import (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from ._route_list import _RouteList
from ._route import _Route, _agentic_selector
from .route_rank import RouteRank

__all__ = [
"_RouteList",
"_Route",
"RouteRank",
"_agentic_selector",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from __future__ import annotations

from typing import Generic, Optional, TypeVar

from ...turn_context import TurnContext
from .._type_defs import RouteHandler, RouteSelector
from ..state.turn_state import TurnState
from .route_rank import RouteRank


def _agentic_selector(selector: RouteSelector) -> RouteSelector:
def wrapped_selector(context: TurnContext) -> bool:
return context.activity.is_agentic_request() and selector(context)

return wrapped_selector


StateT = TypeVar("StateT", bound=TurnState)


class _Route(Generic[StateT]):
selector: RouteSelector
handler: RouteHandler[StateT]
_is_invoke: bool
_rank: int
auth_handlers: list[str]
_is_agentic: bool

def __init__(
self,
selector: RouteSelector,
handler: RouteHandler[StateT],
is_invoke: bool = False,
rank: int = RouteRank.DEFAULT,
auth_handlers: Optional[list[str]] = None,
is_agentic: bool = False,
**kwargs,
) -> None:

if rank < 0 or rank > RouteRank.LAST:
raise ValueError(
"Route rank must be between 0 and RouteRank.LAST (inclusive)"
)

self.selector = selector
self.handler = handler
self._is_invoke = is_invoke
self._rank = int(rank) # conversion from RouteRank IntEnum if necessary
self._is_agentic = is_agentic
self.auth_handlers = auth_handlers or []

@property
def is_invoke(self) -> bool:
return self._is_invoke

@property
def rank(self) -> int:
return self._rank

@property
def is_agentic(self) -> bool:
return self._is_agentic

@property
def priority(self) -> list[int]:
"""Lower "values" indicate higher priority.

Priority is determined by:
1. Whether the route is for an invoke activity (0) or not (1).
2. Whether the route is agentic (0) or not (1).
3. The rank of the route (lower numbers indicate higher priority).

In that order. If both are invokes, the agentic one has higher priority.
If both are agentic and invokes, then the rank determines priority.

priority is represented as a list of three integers for easy lexicographic comparison.
"""
return [
0 if self._is_invoke else 1,
0 if self._is_agentic else 1,
self._rank,
]

def __lt__(self, other: _Route) -> bool:
# built-in list ordering is a lexicographic comparison in Python
return self.priority < other.priority
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from __future__ import annotations

import heapq
from typing import Generic, TypeVar

from ..state.turn_state import TurnState
from ._route import _Route

StateT = TypeVar("StateT", bound=TurnState)


class _RouteList(Generic[StateT]):
_routes: list[_Route[StateT]]

def __init__(
self,
) -> None:
# a min-heap where lower "values" indicate higher priority
self._routes = []

def add_route(self, route: _Route[StateT]) -> None:
"""Adds a route to the list."""
heapq.heappush(self._routes, route)

def __iter__(self):
# sorted will return a new list, leaving the heap intact
# returning an iterator over the previous list would expose
# internal details
return iter(sorted(self._routes))
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from enum import IntEnum

_MAX_RANK = 2**16 - 1 # 65,535


class RouteRank(IntEnum):
"""Defines the rank of a route. Lower values indicate higher priority."""

FIRST = 0
DEFAULT = _MAX_RANK // 2
LAST = _MAX_RANK
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from typing import Callable, TypeVar, Awaitable, Protocol

from ..turn_context import TurnContext
from .state import TurnState

RouteSelector = Callable[[TurnContext], bool]

StateT = TypeVar("StateT", bound=TurnState)


class RouteHandler(Protocol[StateT]):
def __call__(self, context: TurnContext, state: StateT) -> Awaitable[None]: ...
Loading