Skip to content
This repository was archived by the owner on Jan 5, 2026. It is now read-only.

Commit 41cfc8a

Browse files
authored
Merge branch 'main' into main
2 parents e8848e8 + 72fa3be commit 41cfc8a

File tree

23 files changed

+171
-28
lines changed

23 files changed

+171
-28
lines changed

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# ![Bot Framework SDK v4 Python](./doc/media/FrameWorkPython.png)
22

3+
# ARCHIVE NOTICE:
4+
5+
> We are in the process of archiving the Bot Framework Python SDK repository on GitHub. This means that this project will no longer be updated or maintained. Customers using this tool will not be disrupted. However, the tool will no longer be supported through
6+
> service tickets in the Azure portal and will not receive product updates.
7+
8+
> To build agents with your choice of AI services, orchestration, and knowledge, consider using the [Microsoft 365 Agents SDK](https://github.com/microsoft/agents). The Agents SDK is GA and has support for C#, JavaScript or Python. You can learn more about the Agents SDK at aka.ms/agents. If you're looking for a SaaS-based agent platform, consider Microsoft Copilot Studio. If you have an existing bot built with the Bot Framework SDK, you can update your bot to the Agents SDK. You can review the core changes and updates at Bot Framework SDK to Agents SDK migration guidance [here](https://learn.microsoft.com/en-us/microsoft-365/agents-sdk/bf-migration-guidance). Support tickets for the Bot Framework SDK will no longer be serviced as of December 31, 2025.
9+
10+
> We plan to archive this project no later than end of December of 2025.
11+
312
This repository contains code for the Python version of the [Microsoft Bot Framework SDK](https://github.com/Microsoft/botframework-sdk), which is part of the Microsoft Bot Framework - a comprehensive framework for building enterprise-grade conversational AI experiences.
413

514
This SDK enables developers to model conversation and build sophisticated bot applications using Python. SDKs for [JavaScript](https://github.com/Microsoft/botbuilder-js) and [.NET](https://github.com/Microsoft/botbuilder-dotnet) are also available.
@@ -118,7 +127,7 @@ We use the [@msbotframework](https://twitter.com/msbotframework) account on twit
118127
The [Gitter Channel](https://gitter.im/Microsoft/BotBuilder) provides a place where the Community can get together and collaborate.
119128

120129
## Contributing and our code of conduct
121-
We welcome contributions and suggestions. Please see our [contributing guidelines](./contributing.md) for more information.
130+
We welcome contributions and suggestions. Please see our [contributing guidelines](./Contributing.md) for more information.
122131

123132
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
124133

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
aiohttp==3.10.11
1+
aiohttp
22
pyslack
33
botbuilder-core==4.17.0
44
slackclient

libraries/botbuilder-ai/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"azure-cognitiveservices-language-luis==0.2.0",
99
"botbuilder-schema==4.17.0",
1010
"botbuilder-core==4.17.0",
11-
"aiohttp==3.10.11",
11+
"aiohttp>=3.10,<4.0",
1212
]
1313

1414
TESTS_REQUIRES = ["aiounittest>=1.1.0"]

libraries/botbuilder-azure/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"azure-storage-queue==12.4.0",
1111
"botbuilder-schema==4.17.0",
1212
"botframework-connector==4.17.0",
13-
"jsonpickle>=1.2,<1.5",
13+
"jsonpickle>=1.2,<4",
1414
]
1515
TEST_REQUIRES = ["aiounittest==1.3.0"]
1616

libraries/botbuilder-core/botbuilder/core/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
from .user_state import UserState
4949
from .register_class_middleware import RegisterClassMiddleware
5050
from .adapter_extensions import AdapterExtensions
51+
from .serializer_helper import serializer_helper
5152

5253
__all__ = [
5354
"ActivityHandler",
@@ -100,5 +101,6 @@
100101
"TurnContext",
101102
"UserState",
102103
"UserTokenProvider",
104+
"serializer_helper",
103105
"__version__",
104106
]

libraries/botbuilder-core/botbuilder/core/activity_handler.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,12 +478,19 @@ async def on_invoke_activity( # pylint: disable=unused-argument
478478
if (
479479
turn_context.activity.name
480480
== SignInConstants.verify_state_operation_name
481-
or turn_context.activity.name
482-
== SignInConstants.token_exchange_operation_name
483481
):
484482
await self.on_sign_in_invoke(turn_context)
485483
return self._create_invoke_response()
486484

485+
# This is for back-compat with previous versions of Python SDK. This method does not
486+
# exist in the C# SDK, and is not used in the Python SDK.
487+
if (
488+
turn_context.activity.name
489+
== SignInConstants.token_exchange_operation_name
490+
):
491+
await self.on_teams_signin_token_exchange(turn_context)
492+
return self._create_invoke_response()
493+
487494
if turn_context.activity.name == "adaptiveCard/action":
488495
invoke_value = self._get_adaptive_card_invoke_value(
489496
turn_context.activity

libraries/botbuilder-core/botbuilder/core/teams/teams_activity_handler.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,6 @@ async def on_invoke_activity(self, turn_context: TurnContext) -> InvokeResponse:
5656
):
5757
return await self.on_teams_card_action_invoke(turn_context)
5858

59-
if (
60-
turn_context.activity.name
61-
== SignInConstants.token_exchange_operation_name
62-
):
63-
await self.on_teams_signin_token_exchange(turn_context)
64-
return self._create_invoke_response()
65-
6659
if turn_context.activity.name == "fileConsent/invoke":
6760
return await self.on_teams_file_consent(
6861
turn_context,
@@ -250,7 +243,9 @@ async def on_teams_signin_verify_state(self, turn_context: TurnContext):
250243
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)
251244

252245
async def on_teams_signin_token_exchange(self, turn_context: TurnContext):
253-
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)
246+
# This is for back-compat with previous versions of Python SDK. This method does not
247+
# exist in the C# SDK, and is not used in the Python SDK.
248+
return await self.on_teams_signin_verify_state(turn_context)
254249

255250
async def on_teams_file_consent(
256251
self,
@@ -319,7 +314,7 @@ async def on_teams_o365_connector_card_action( # pylint: disable=unused-argumen
319314
self, turn_context: TurnContext, query: O365ConnectorCardActionQuery
320315
):
321316
"""
322-
Invoked when a O365 Connector Card Action activity is received from the connector.
317+
Invoked when an O365 Connector Card Action activity is received from the connector.
323318
324319
:param turn_context: A context object for this turn.
325320
:param query: The O365 connector card HttpPOST invoke query.

libraries/botbuilder-core/botbuilder/core/teams/teams_sso_token_exchange_middleware.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
StoreItem,
2727
TurnContext,
2828
)
29+
from botframework.connector.auth.user_token_client import UserTokenClient
2930

3031

3132
class _TokenStoreItem(StoreItem):
@@ -147,17 +148,29 @@ async def _exchanged_token(self, turn_context: TurnContext) -> bool:
147148
token_exchange_response: TokenResponse = None
148149
aux_dict = {}
149150
if turn_context.activity.value:
150-
for prop in ["id", "connection_name", "token", "properties"]:
151+
for prop in ["id", "connectionName", "token", "properties"]:
151152
aux_dict[prop] = turn_context.activity.value.get(prop)
152153
token_exchange_request = TokenExchangeInvokeRequest(
153154
id=aux_dict["id"],
154-
connection_name=aux_dict["connection_name"],
155+
connection_name=aux_dict["connectionName"],
155156
token=aux_dict["token"],
156157
properties=aux_dict["properties"],
157158
)
158159
try:
159160
adapter = turn_context.adapter
160-
if isinstance(turn_context.adapter, ExtendedUserTokenProvider):
161+
162+
user_token_client: UserTokenClient = turn_context.turn_state.get(
163+
UserTokenClient.__name__, None
164+
)
165+
if user_token_client:
166+
# If the adapter has UserTokenClient, use it to exchange the token.
167+
token_exchange_response = await user_token_client.exchange_token(
168+
turn_context.activity.from_property.id,
169+
token_exchange_request.connection_name,
170+
turn_context.activity.channel_id,
171+
TokenExchangeRequest(token=token_exchange_request.token),
172+
)
173+
elif isinstance(turn_context.adapter, ExtendedUserTokenProvider):
161174
token_exchange_response = await adapter.exchange_token(
162175
turn_context,
163176
self._oauth_connection_name,

libraries/botbuilder-core/botbuilder/core/turn_context.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,9 +396,13 @@ def remove_mention_text(activity: Activity, identifier: str) -> str:
396396
mentions = TurnContext.get_mentions(activity)
397397
for mention in mentions:
398398
if mention.additional_properties["mentioned"]["id"] == identifier:
399+
replace_text = (
400+
mention.additional_properties.get("text")
401+
or mention.additional_properties.get("mentioned")["name"]
402+
)
399403
mention_name_match = re.match(
400404
r"<at(.*)>(.*?)<\/at>",
401-
escape(mention.additional_properties["text"]),
405+
escape(replace_text),
402406
re.IGNORECASE,
403407
)
404408
if mention_name_match:

libraries/botbuilder-core/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"botbuilder-schema==4.17.0",
1010
"botframework-connector==4.17.0",
1111
"botframework-streaming==4.17.0",
12-
"jsonpickle>=1.2,<1.5",
12+
"jsonpickle>=1.2,<4",
1313
]
1414

1515
root = os.path.abspath(os.path.dirname(__file__))

0 commit comments

Comments
 (0)