microsoft-teams-botbuilder 2.0.0a6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,45 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+
7
+ # Environments
8
+ .env
9
+ .venv
10
+ env/
11
+ venv/
12
+ ENV/
13
+ env.bak/
14
+ venv.bak/
15
+
16
+ # mypy
17
+ .mypy_cache/
18
+ .dmypy.json
19
+ dmypy.json
20
+
21
+ .copilot-instructions.md
22
+
23
+ # other
24
+ .DS_STORE
25
+ *.bak
26
+ *~
27
+ *.tmp
28
+
29
+ ref/
30
+ py.typed
31
+ CLAUDE.md
32
+
33
+ .env.claude/
34
+ .claude/
35
+
36
+ examples/**/.vscode/
37
+ examples/**/appPackage/
38
+ examples/**/infra/
39
+ examples/**/teamsapp*
40
+ examples/**/aad.manifest.json
41
+
42
+ # Node (from tab)
43
+ node_modules
44
+ dist/
45
+ build/
@@ -0,0 +1,33 @@
1
+ Metadata-Version: 2.4
2
+ Name: microsoft-teams-botbuilder
3
+ Version: 2.0.0a6
4
+ Summary: BotBuilder plugin for Microsoft Teams
5
+ Project-URL: Homepage, https://github.com/microsoft/teams.py/tree/main/packages/botbuilder/src/microsoft/teams/botbuilder
6
+ Author-email: Microsoft <TeamsAISDKFeedback@microsoft.com>
7
+ License-Expression: MIT
8
+ Keywords: agents,ai,bot,microsoft,teams
9
+ Requires-Python: <3.14,>=3.12
10
+ Requires-Dist: botbuilder-core>=4.14.0
11
+ Requires-Dist: botbuilder-integration-aiohttp>=4.17.0
12
+ Requires-Dist: microsoft-teams-api
13
+ Requires-Dist: microsoft-teams-apps
14
+ Requires-Dist: microsoft-teams-common
15
+ Description-Content-Type: text/markdown
16
+
17
+ # Microsoft Teams BotBuilder
18
+
19
+ <p>
20
+ <a href="https://pypi.org/project/microsoft-teams-botbuilder/" target="_blank">
21
+ <img src="https://img.shields.io/pypi/v/microsoft-teams-botbuilder" />
22
+ </a>
23
+ <a href="https://pypi.org/project/microsoft-teams-botbuilder" target="_blank">
24
+ <img src="https://img.shields.io/pypi/dw/microsoft-teams-botbuilder" />
25
+ </a>
26
+ </p>
27
+
28
+ A package used to make the `@microsoft/teams.apps` package backwards compatible with legacy bots built using
29
+ `BotBuilder`.
30
+
31
+ <a href="https://microsoft.github.io/teams-ai" target="_blank">
32
+ <img src="https://img.shields.io/badge/📖 Getting Started-blue?style=for-the-badge" />
33
+ </a>
@@ -0,0 +1,17 @@
1
+ # Microsoft Teams BotBuilder
2
+
3
+ <p>
4
+ <a href="https://pypi.org/project/microsoft-teams-botbuilder/" target="_blank">
5
+ <img src="https://img.shields.io/pypi/v/microsoft-teams-botbuilder" />
6
+ </a>
7
+ <a href="https://pypi.org/project/microsoft-teams-botbuilder" target="_blank">
8
+ <img src="https://img.shields.io/pypi/dw/microsoft-teams-botbuilder" />
9
+ </a>
10
+ </p>
11
+
12
+ A package used to make the `@microsoft/teams.apps` package backwards compatible with legacy bots built using
13
+ `BotBuilder`.
14
+
15
+ <a href="https://microsoft.github.io/teams-ai" target="_blank">
16
+ <img src="https://img.shields.io/badge/📖 Getting Started-blue?style=for-the-badge" />
17
+ </a>
@@ -0,0 +1,36 @@
1
+ [project]
2
+ name = "microsoft-teams-botbuilder"
3
+ version = "2.0.0a6"
4
+ description = "BotBuilder plugin for Microsoft Teams"
5
+ authors = [{ name = "Microsoft", email = "TeamsAISDKFeedback@microsoft.com" }]
6
+ readme = "README.md"
7
+ requires-python = ">=3.12,<3.14"
8
+ repository = "https://github.com/microsoft/teams.py"
9
+ keywords = ["microsoft", "teams", "ai", "bot", "agents"]
10
+ license = "MIT"
11
+ dependencies = [
12
+ "botbuilder-core>=4.14.0",
13
+ "botbuilder-integration-aiohttp>=4.17.0",
14
+ "microsoft-teams-apps",
15
+ "microsoft-teams-api",
16
+ "microsoft-teams-common"
17
+ ]
18
+
19
+ [project.urls]
20
+ Homepage = "https://github.com/microsoft/teams.py/tree/main/packages/botbuilder/src/microsoft/teams/botbuilder"
21
+
22
+
23
+ [build-system]
24
+ requires = ["hatchling"]
25
+ build-backend = "hatchling.build"
26
+
27
+ [tool.hatch.build.targets.wheel]
28
+ packages = ["src/microsoft"]
29
+
30
+ [tool.hatch.build.targets.sdist]
31
+ include = ["src"]
32
+
33
+ [tool.uv.sources]
34
+ microsoft-teams-apps = { workspace = true }
35
+ microsoft-teams-api = { workspace = true }
36
+ microsoft-teams-common = { workspace = true }
@@ -0,0 +1,8 @@
1
+ """
2
+ Copyright (c) Microsoft Corporation. All rights reserved.
3
+ Licensed under the MIT License.
4
+ """
5
+
6
+ from .botbuilder_plugin import BotBuilderPlugin, BotBuilderPluginOptions
7
+
8
+ __all__ = ["BotBuilderPlugin", "BotBuilderPluginOptions"]
@@ -0,0 +1,138 @@
1
+ """
2
+ Copyright (c) Microsoft Corporation. All rights reserved.
3
+ Licensed under the MIT License.
4
+ """
5
+
6
+ import importlib.metadata
7
+ from logging import Logger
8
+ from types import SimpleNamespace
9
+ from typing import Annotated, Any, Optional, Unpack, cast
10
+
11
+ from fastapi import HTTPException, Request, Response
12
+ from microsoft.teams.api import Credentials
13
+ from microsoft.teams.apps import (
14
+ DependencyMetadata,
15
+ HttpPlugin,
16
+ LoggerDependencyOptions,
17
+ Plugin,
18
+ )
19
+ from microsoft.teams.apps.http_plugin import HttpPluginOptions
20
+
21
+ from botbuilder.core import (
22
+ ActivityHandler,
23
+ TurnContext,
24
+ )
25
+ from botbuilder.integration.aiohttp import (
26
+ CloudAdapter,
27
+ ConfigurationBotFrameworkAuthentication,
28
+ )
29
+ from botbuilder.schema import Activity
30
+
31
+ version = importlib.metadata.version("microsoft-teams-botbuilder")
32
+
33
+ # Constants for app types
34
+ SINGLE_TENANT = "singletenant"
35
+ MULTI_TENANT = "multitenant"
36
+
37
+
38
+ class BotBuilderPluginOptions(HttpPluginOptions, total=False):
39
+ """Options for configuring the BotBuilder plugin."""
40
+
41
+ handler: ActivityHandler
42
+ adapter: CloudAdapter
43
+
44
+
45
+ @Plugin(name="http", version=version, description="BotBuilder plugin for Microsoft Bot Framework integration")
46
+ class BotBuilderPlugin(HttpPlugin):
47
+ """
48
+ BotBuilder plugin that provides Microsoft Bot Framework integration.
49
+ """
50
+
51
+ # Dependency injections
52
+ logger: Annotated[Logger, LoggerDependencyOptions()]
53
+ credentials: Annotated[Optional[Credentials], DependencyMetadata(optional=True)]
54
+
55
+ def __init__(self, **options: Unpack[BotBuilderPluginOptions]):
56
+ """
57
+ Initialize the BotBuilder plugin.
58
+
59
+ Args:
60
+ options: Configuration options for the plugin
61
+ """
62
+
63
+ self.handler: Optional[ActivityHandler] = options.get("handler")
64
+ self.adapter: Optional[CloudAdapter] = options.get("adapter")
65
+
66
+ super().__init__(**options)
67
+
68
+ async def on_init(self) -> None:
69
+ """Initialize the plugin when the app starts."""
70
+ await super().on_init()
71
+
72
+ if not self.adapter:
73
+ # Extract credentials for Bot Framework authentication
74
+ client_id: Optional[str] = None
75
+ client_secret: Optional[str] = None
76
+ tenant_id: Optional[str] = None
77
+
78
+ if self.credentials:
79
+ client_id = getattr(self.credentials, "client_id", None)
80
+ client_secret = getattr(self.credentials, "client_secret", None)
81
+ tenant_id = getattr(self.credentials, "tenant_id", None)
82
+
83
+ config = SimpleNamespace(
84
+ APP_TYPE=SINGLE_TENANT if tenant_id else MULTI_TENANT,
85
+ APP_ID=client_id,
86
+ APP_PASSWORD=client_secret,
87
+ APP_TENANTID=tenant_id,
88
+ )
89
+
90
+ bot_framework_auth = ConfigurationBotFrameworkAuthentication(configuration=config)
91
+ self.adapter = CloudAdapter(bot_framework_auth)
92
+
93
+ self.logger.debug("BotBuilder plugin initialized successfully")
94
+
95
+ async def on_activity_request(self, request: Request, response: Response) -> Any:
96
+ """
97
+ Handles an incoming activity.
98
+
99
+ Overrides the base HTTP plugin behavior to:
100
+ 1. Process the activity using the Bot Framework adapter/handler.
101
+ 2. Then pass the request to the Teams plugin pipeline (_handle_activity_request).
102
+
103
+ Returns the final HTTP response.
104
+ """
105
+ if not self.adapter:
106
+ raise RuntimeError("plugin not registered")
107
+
108
+ try:
109
+ # Parse activity data
110
+ body = await request.json()
111
+ activity_bf = cast(Activity, Activity().deserialize(body))
112
+
113
+ # A POST request must contain an Activity
114
+ if not activity_bf.type:
115
+ raise HTTPException(status_code=400, detail="Missing activity type")
116
+
117
+ async def logic(turn_context: TurnContext):
118
+ if not turn_context.activity.id:
119
+ return
120
+
121
+ # Handle activity with botframework handler
122
+ if self.handler:
123
+ await self.handler.on_turn(turn_context)
124
+
125
+ # Grab the auth header from the inbound request
126
+ auth_header = request.headers["Authorization"] if "Authorization" in request.headers else ""
127
+ await self.adapter.process_activity(auth_header, activity_bf, logic)
128
+
129
+ # Call HTTP plugin to handle activity request
130
+ result = await self._handle_activity_request(request)
131
+ return self._handle_activity_response(response, result)
132
+
133
+ except HTTPException as http_err:
134
+ self.logger.error(f"HTTP error processing activity: {http_err}", exc_info=True)
135
+ raise
136
+ except Exception as err:
137
+ self.logger.error(f"Error processing activity: {err}", exc_info=True)
138
+ raise HTTPException(status_code=500, detail=str(err)) from err