microsoft-agents-hosting-core 0.4.0.dev18__py3-none-any.whl → 0.5.0__py3-none-any.whl
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.
- microsoft_agents/hosting/core/_oauth/_flow_state.py +2 -2
- microsoft_agents/hosting/core/_oauth/_oauth_flow.py +26 -23
- microsoft_agents/hosting/core/activity_handler.py +19 -17
- microsoft_agents/hosting/core/app/agent_application.py +37 -13
- microsoft_agents/hosting/core/app/input_file.py +15 -11
- microsoft_agents/hosting/core/app/oauth/_handlers/_authorization_handler.py +4 -4
- microsoft_agents/hosting/core/app/oauth/_handlers/_user_authorization.py +2 -2
- microsoft_agents/hosting/core/app/oauth/_handlers/agentic_user_authorization.py +9 -9
- microsoft_agents/hosting/core/app/oauth/authorization.py +38 -20
- microsoft_agents/hosting/core/app/state/state.py +50 -6
- microsoft_agents/hosting/core/app/typing_indicator.py +51 -27
- microsoft_agents/hosting/core/authorization/access_token_provider_base.py +1 -1
- microsoft_agents/hosting/core/authorization/anonymous_token_provider.py +1 -1
- microsoft_agents/hosting/core/authorization/jwt_token_validator.py +6 -4
- microsoft_agents/hosting/core/channel_adapter.py +9 -9
- microsoft_agents/hosting/core/channel_service_adapter.py +64 -6
- microsoft_agents/hosting/core/connector/client/connector_client.py +1 -1
- microsoft_agents/hosting/core/connector/client/user_token_client.py +40 -43
- microsoft_agents/hosting/core/connector/user_token_base.py +77 -1
- microsoft_agents/hosting/core/connector/user_token_client_base.py +3 -0
- microsoft_agents/hosting/core/state/agent_state.py +16 -20
- microsoft_agents/hosting/core/storage/transcript_file_store.py +1 -5
- microsoft_agents/hosting/core/turn_context.py +2 -1
- microsoft_agents_hosting_core-0.5.0.dist-info/METADATA +191 -0
- {microsoft_agents_hosting_core-0.4.0.dev18.dist-info → microsoft_agents_hosting_core-0.5.0.dist-info}/RECORD +28 -27
- microsoft_agents_hosting_core-0.5.0.dist-info/licenses/LICENSE +21 -0
- microsoft_agents_hosting_core-0.4.0.dev18.dist-info/METADATA +0 -16
- {microsoft_agents_hosting_core-0.4.0.dev18.dist-info → microsoft_agents_hosting_core-0.5.0.dist-info}/WHEEL +0 -0
- {microsoft_agents_hosting_core-0.4.0.dev18.dist-info → microsoft_agents_hosting_core-0.5.0.dist-info}/top_level.txt +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
|
-
from datetime import datetime
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
7
|
from enum import Enum
|
|
8
8
|
from typing import Optional
|
|
9
9
|
|
|
@@ -60,7 +60,7 @@ class _FlowState(BaseModel, StoreItem):
|
|
|
60
60
|
return _FlowState.model_validate(json_data)
|
|
61
61
|
|
|
62
62
|
def is_expired(self) -> bool:
|
|
63
|
-
return datetime.now().timestamp() >= self.expiration
|
|
63
|
+
return datetime.now(timezone.utc).timestamp() >= self.expiration
|
|
64
64
|
|
|
65
65
|
def reached_max_attempts(self) -> bool:
|
|
66
66
|
return self.attempts_remaining <= 0
|
|
@@ -6,7 +6,7 @@ from __future__ import annotations
|
|
|
6
6
|
import logging
|
|
7
7
|
|
|
8
8
|
from pydantic import BaseModel
|
|
9
|
-
from datetime import datetime
|
|
9
|
+
from datetime import datetime, timezone
|
|
10
10
|
from typing import Optional
|
|
11
11
|
|
|
12
12
|
from microsoft_agents.activity import (
|
|
@@ -30,7 +30,6 @@ class _FlowResponse(BaseModel):
|
|
|
30
30
|
flow_error_tag: _FlowErrorTag = _FlowErrorTag.NONE
|
|
31
31
|
token_response: Optional[TokenResponse] = None
|
|
32
32
|
sign_in_resource: Optional[SignInResource] = None
|
|
33
|
-
continuation_activity: Optional[Activity] = None
|
|
34
33
|
|
|
35
34
|
|
|
36
35
|
class _OAuthFlow:
|
|
@@ -112,7 +111,7 @@ class _OAuthFlow:
|
|
|
112
111
|
"""Get the user token based on the context.
|
|
113
112
|
|
|
114
113
|
Args:
|
|
115
|
-
magic_code (str,
|
|
114
|
+
magic_code (str, Optional): Defaults to None. The magic code for user authentication.
|
|
116
115
|
|
|
117
116
|
Returns:
|
|
118
117
|
TokenResponse
|
|
@@ -137,7 +136,7 @@ class _OAuthFlow:
|
|
|
137
136
|
if token_response:
|
|
138
137
|
logger.info("User token obtained successfully: %s", token_response)
|
|
139
138
|
self._flow_state.expiration = (
|
|
140
|
-
datetime.now().timestamp() + self._default_flow_duration
|
|
139
|
+
datetime.now(timezone.utc).timestamp() + self._default_flow_duration
|
|
141
140
|
)
|
|
142
141
|
self._flow_state.tag = _FlowStateTag.COMPLETE
|
|
143
142
|
|
|
@@ -183,20 +182,8 @@ class _OAuthFlow:
|
|
|
183
182
|
Notes:
|
|
184
183
|
The flow state is reset if a token is not obtained from cache.
|
|
185
184
|
"""
|
|
186
|
-
token_response = await self.get_user_token()
|
|
187
|
-
if token_response:
|
|
188
|
-
return _FlowResponse(
|
|
189
|
-
flow_state=self._flow_state, token_response=token_response
|
|
190
|
-
)
|
|
191
185
|
|
|
192
186
|
logger.debug("Starting new OAuth flow")
|
|
193
|
-
self._flow_state.tag = _FlowStateTag.BEGIN
|
|
194
|
-
self._flow_state.expiration = (
|
|
195
|
-
datetime.now().timestamp() + self._default_flow_duration
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
self._flow_state.attempts_remaining = self._max_attempts
|
|
199
|
-
self._flow_state.continuation_activity = activity.model_copy()
|
|
200
187
|
|
|
201
188
|
token_exchange_state = TokenExchangeState(
|
|
202
189
|
connection_name=self._abs_oauth_connection_name,
|
|
@@ -205,16 +192,33 @@ class _OAuthFlow:
|
|
|
205
192
|
ms_app_id=self._ms_app_id,
|
|
206
193
|
)
|
|
207
194
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
195
|
+
res = await self._user_token_client.user_token._get_token_or_sign_in_resource(
|
|
196
|
+
activity.from_property.id,
|
|
197
|
+
self._abs_oauth_connection_name,
|
|
198
|
+
activity.channel_id,
|
|
199
|
+
token_exchange_state.get_encoded_state(),
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
if res.token_response:
|
|
203
|
+
logger.info("Skipping flow, user token obtained.")
|
|
204
|
+
self._flow_state.tag = _FlowStateTag.COMPLETE
|
|
205
|
+
self._flow_state.expiration = (
|
|
206
|
+
datetime.now(timezone.utc).timestamp() + self._default_flow_duration
|
|
207
|
+
)
|
|
208
|
+
return _FlowResponse(
|
|
209
|
+
flow_state=self._flow_state, token_response=res.token_response
|
|
211
210
|
)
|
|
211
|
+
|
|
212
|
+
self._flow_state.tag = _FlowStateTag.BEGIN
|
|
213
|
+
self._flow_state.expiration = (
|
|
214
|
+
datetime.now(timezone.utc).timestamp() + self._default_flow_duration
|
|
212
215
|
)
|
|
216
|
+
self._flow_state.attempts_remaining = self._max_attempts
|
|
213
217
|
|
|
214
|
-
logger.debug("Sign-in resource obtained successfully: %s", sign_in_resource)
|
|
218
|
+
logger.debug("Sign-in resource obtained successfully: %s", res.sign_in_resource)
|
|
215
219
|
|
|
216
220
|
return _FlowResponse(
|
|
217
|
-
flow_state=self._flow_state, sign_in_resource=sign_in_resource
|
|
221
|
+
flow_state=self._flow_state, sign_in_resource=res.sign_in_resource
|
|
218
222
|
)
|
|
219
223
|
|
|
220
224
|
async def _continue_from_message(
|
|
@@ -299,7 +303,7 @@ class _OAuthFlow:
|
|
|
299
303
|
else:
|
|
300
304
|
self._flow_state.tag = _FlowStateTag.COMPLETE
|
|
301
305
|
self._flow_state.expiration = (
|
|
302
|
-
datetime.now().timestamp() + self._default_flow_duration
|
|
306
|
+
datetime.now(timezone.utc).timestamp() + self._default_flow_duration
|
|
303
307
|
)
|
|
304
308
|
logger.debug(
|
|
305
309
|
"OAuth flow completed successfully, got TokenResponse: %s",
|
|
@@ -310,7 +314,6 @@ class _OAuthFlow:
|
|
|
310
314
|
flow_state=self._flow_state.model_copy(),
|
|
311
315
|
flow_error_tag=flow_error_tag,
|
|
312
316
|
token_response=token_response,
|
|
313
|
-
continuation_activity=self._flow_state.continuation_activity,
|
|
314
317
|
)
|
|
315
318
|
|
|
316
319
|
async def begin_or_continue_flow(self, activity: Activity) -> _FlowResponse:
|
|
@@ -38,7 +38,7 @@ class ActivityHandler(Agent):
|
|
|
38
38
|
in order to process an inbound :class:`microsoft_agents.activity.Activity`.
|
|
39
39
|
|
|
40
40
|
:param turn_context: The context object for this turn
|
|
41
|
-
:type turn_context: :class:`microsoft_agents.
|
|
41
|
+
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
42
42
|
|
|
43
43
|
:returns: A task that represents the work queued to execute
|
|
44
44
|
|
|
@@ -143,7 +143,7 @@ class ActivityHandler(Agent):
|
|
|
143
143
|
:meth:`on_turn()` is used.
|
|
144
144
|
|
|
145
145
|
:param turn_context: The context object for this turn
|
|
146
|
-
:type turn_context: :class:`microsoft_agents.
|
|
146
|
+
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
147
147
|
:returns: A task that represents the work queued to execute
|
|
148
148
|
|
|
149
149
|
.. remarks::
|
|
@@ -176,7 +176,7 @@ class ActivityHandler(Agent):
|
|
|
176
176
|
|
|
177
177
|
:param members_added: A list of all the members added to the conversation, as described by the
|
|
178
178
|
conversation update activity
|
|
179
|
-
:type members_added: list[ChannelAccount]
|
|
179
|
+
:type members_added: list[:class:`microsoft_agents.activity.ChannelAccount`]
|
|
180
180
|
:param turn_context: The context object for this turn
|
|
181
181
|
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
182
182
|
:returns: A task that represents the work queued to execute
|
|
@@ -195,9 +195,9 @@ class ActivityHandler(Agent):
|
|
|
195
195
|
Override this method in a derived class to provide logic for when members other than the agent leave
|
|
196
196
|
the conversation. You can add your agent's good-bye logic.
|
|
197
197
|
|
|
198
|
-
:param
|
|
198
|
+
:param members_removed: A list of all the members removed from the conversation, as described by the
|
|
199
199
|
conversation update activity
|
|
200
|
-
:type
|
|
200
|
+
:type members_removed: list[:class:`microsoft_agents.activity.ChannelAccount`]
|
|
201
201
|
:param turn_context: The context object for this turn
|
|
202
202
|
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
203
203
|
:returns: A task that represents the work queued to execute
|
|
@@ -216,7 +216,7 @@ class ActivityHandler(Agent):
|
|
|
216
216
|
:meth:`on_turn()` is used.
|
|
217
217
|
|
|
218
218
|
:param turn_context: The context object for this turn
|
|
219
|
-
:type turn_context: :class:`microsoft_agents.
|
|
219
|
+
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
220
220
|
|
|
221
221
|
:returns: A task that represents the work queued to execute
|
|
222
222
|
|
|
@@ -260,7 +260,7 @@ class ActivityHandler(Agent):
|
|
|
260
260
|
are added to the conversation.
|
|
261
261
|
|
|
262
262
|
:param message_reactions: The list of reactions added
|
|
263
|
-
:type message_reactions: list[MessageReaction]
|
|
263
|
+
:type message_reactions: list[:class:`microsoft_agents.activity.MessageReaction`]
|
|
264
264
|
:param turn_context: The context object for this turn
|
|
265
265
|
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
266
266
|
:returns: A task that represents the work queued to execute
|
|
@@ -285,7 +285,7 @@ class ActivityHandler(Agent):
|
|
|
285
285
|
are removed from the conversation.
|
|
286
286
|
|
|
287
287
|
:param message_reactions: The list of reactions removed
|
|
288
|
-
:type message_reactions: list[MessageReaction]
|
|
288
|
+
:type message_reactions: list[:class:`microsoft_agents.activity.MessageReaction`]
|
|
289
289
|
:param turn_context: The context object for this turn
|
|
290
290
|
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
291
291
|
|
|
@@ -382,7 +382,7 @@ class ActivityHandler(Agent):
|
|
|
382
382
|
ActivityTypes.typing activities, such as the conversational logic.
|
|
383
383
|
|
|
384
384
|
:param turn_context: The context object for this turn
|
|
385
|
-
:type turn_context: :class:`microsoft_agents.
|
|
385
|
+
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
386
386
|
:returns: A task that represents the work queued to execute
|
|
387
387
|
"""
|
|
388
388
|
return
|
|
@@ -395,7 +395,7 @@ class ActivityHandler(Agent):
|
|
|
395
395
|
ActivityTypes.InstallationUpdate activities.
|
|
396
396
|
|
|
397
397
|
:param turn_context: The context object for this turn
|
|
398
|
-
:type turn_context: :class:`microsoft_agents.
|
|
398
|
+
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
399
399
|
:returns: A task that represents the work queued to execute
|
|
400
400
|
"""
|
|
401
401
|
if turn_context.activity.action in ("add", "add-upgrade"):
|
|
@@ -412,7 +412,7 @@ class ActivityHandler(Agent):
|
|
|
412
412
|
ActivityTypes.InstallationUpdate activities with 'action' set to 'add'.
|
|
413
413
|
|
|
414
414
|
:param turn_context: The context object for this turn
|
|
415
|
-
:type turn_context: :class:`microsoft_agents.
|
|
415
|
+
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
416
416
|
:returns: A task that represents the work queued to execute
|
|
417
417
|
"""
|
|
418
418
|
return
|
|
@@ -425,7 +425,7 @@ class ActivityHandler(Agent):
|
|
|
425
425
|
ActivityTypes.InstallationUpdate activities with 'action' set to 'remove'.
|
|
426
426
|
|
|
427
427
|
:param turn_context: The context object for this turn
|
|
428
|
-
:type turn_context: :class:`microsoft_agents.
|
|
428
|
+
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
429
429
|
:returns: A task that represents the work queued to execute
|
|
430
430
|
"""
|
|
431
431
|
return
|
|
@@ -439,7 +439,7 @@ class ActivityHandler(Agent):
|
|
|
439
439
|
If overridden, this method could potentially respond to any of the other activity types.
|
|
440
440
|
|
|
441
441
|
:param turn_context: The context object for this turn
|
|
442
|
-
:type turn_context: :class:`microsoft_agents.
|
|
442
|
+
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
443
443
|
|
|
444
444
|
:returns: A task that represents the work queued to execute
|
|
445
445
|
|
|
@@ -456,9 +456,10 @@ class ActivityHandler(Agent):
|
|
|
456
456
|
Registers an activity event handler for the _invoke_ event, emitted for every incoming event activity.
|
|
457
457
|
|
|
458
458
|
:param turn_context: The context object for this turn
|
|
459
|
-
:type turn_context: :class:`microsoft_agents.
|
|
459
|
+
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
460
460
|
|
|
461
461
|
:returns: A task that represents the work queued to execute
|
|
462
|
+
:rtype: Optional[:class:`microsoft_agents.activity.InvokeResponse`]
|
|
462
463
|
"""
|
|
463
464
|
try:
|
|
464
465
|
if (
|
|
@@ -492,7 +493,7 @@ class ActivityHandler(Agent):
|
|
|
492
493
|
By default, this method does nothing.
|
|
493
494
|
|
|
494
495
|
:param turn_context: The context object for this turn
|
|
495
|
-
:type turn_context: :class:`microsoft_agents.
|
|
496
|
+
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
496
497
|
|
|
497
498
|
:returns: A task that represents the work queued to execute
|
|
498
499
|
"""
|
|
@@ -508,10 +509,11 @@ class ActivityHandler(Agent):
|
|
|
508
509
|
calls this method.
|
|
509
510
|
|
|
510
511
|
:param turn_context: A context object for this turn.
|
|
511
|
-
:type turn_context: :class:`microsoft_agents.
|
|
512
|
+
:type turn_context: :class:`microsoft_agents.activity.TurnContextProtocol`
|
|
512
513
|
:param invoke_value: A string-typed object from the incoming activity's value.
|
|
513
|
-
:type invoke_value: :class:`microsoft_agents.activity.
|
|
514
|
+
:type invoke_value: :class:`microsoft_agents.activity.AdaptiveCardInvokeValue`
|
|
514
515
|
:return: The HealthCheckResponse object
|
|
516
|
+
:rtype: :class:`microsoft_agents.activity.AdaptiveCardInvokeResponse`
|
|
515
517
|
"""
|
|
516
518
|
raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED)
|
|
517
519
|
|
|
@@ -83,8 +83,16 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
83
83
|
) -> None:
|
|
84
84
|
"""
|
|
85
85
|
Creates a new AgentApplication instance.
|
|
86
|
+
|
|
87
|
+
:param options: Configuration options for the application.
|
|
88
|
+
:type options: Optional[:class:`microsoft_agents.hosting.core.app.app_options.ApplicationOptions`]
|
|
89
|
+
:param connection_manager: OAuth connection manager.
|
|
90
|
+
:type connection_manager: Optional[:class:`microsoft_agents.hosting.core.authorization.Connections`]
|
|
91
|
+
:param authorization: Authorization manager for handling authentication flows.
|
|
92
|
+
:type authorization: Optional[:class:`microsoft_agents.hosting.core.app.oauth.Authorization`]
|
|
93
|
+
:param kwargs: Additional configuration parameters.
|
|
94
|
+
:type kwargs: Any
|
|
86
95
|
"""
|
|
87
|
-
self.typing = TypingIndicator()
|
|
88
96
|
self._route_list = _RouteList[StateT]()
|
|
89
97
|
|
|
90
98
|
configuration = kwargs
|
|
@@ -161,6 +169,10 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
161
169
|
def adapter(self) -> ChannelServiceAdapter:
|
|
162
170
|
"""
|
|
163
171
|
The bot's adapter.
|
|
172
|
+
|
|
173
|
+
:return: The channel service adapter for the bot.
|
|
174
|
+
:rtype: :class:`microsoft_agents.hosting.core.channel_service_adapter.ChannelServiceAdapter`
|
|
175
|
+
:raises ApplicationError: If the adapter is not configured.
|
|
164
176
|
"""
|
|
165
177
|
|
|
166
178
|
if not self._adapter:
|
|
@@ -181,6 +193,10 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
181
193
|
def auth(self) -> Authorization:
|
|
182
194
|
"""
|
|
183
195
|
The application's authentication manager
|
|
196
|
+
|
|
197
|
+
:return: The authentication manager for handling OAuth flows.
|
|
198
|
+
:rtype: :class:`microsoft_agents.hosting.core.app.oauth.Authorization`
|
|
199
|
+
:raises ApplicationError: If authentication is not configured.
|
|
184
200
|
"""
|
|
185
201
|
if not self._auth:
|
|
186
202
|
logger.error(
|
|
@@ -200,6 +216,9 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
200
216
|
def options(self) -> ApplicationOptions:
|
|
201
217
|
"""
|
|
202
218
|
The application's configured options.
|
|
219
|
+
|
|
220
|
+
:return: The configuration options for the application.
|
|
221
|
+
:rtype: :class:`microsoft_agents.hosting.core.app.app_options.ApplicationOptions`
|
|
203
222
|
"""
|
|
204
223
|
return self._options
|
|
205
224
|
|
|
@@ -217,18 +236,18 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
217
236
|
Routes are ordered by: is_agentic, is_invoke, rank (lower is higher priority), in that order.
|
|
218
237
|
|
|
219
238
|
:param selector: A function that takes a TurnContext and returns a boolean indicating whether the route should be selected.
|
|
220
|
-
:type selector: RouteSelector
|
|
239
|
+
:type selector: :class:`microsoft_agents.hosting.core.app._type_defs.RouteSelector`
|
|
221
240
|
:param handler: A function that takes a TurnContext and a TurnState and returns an Awaitable.
|
|
222
|
-
:type handler: RouteHandler[StateT]
|
|
241
|
+
:type handler: :class:`microsoft_agents.hosting.core.app._type_defs.RouteHandler`[StateT]
|
|
223
242
|
:param is_invoke: Whether the route is for an invoke activity, defaults to False
|
|
224
|
-
:type is_invoke: bool,
|
|
243
|
+
:type is_invoke: bool, Optional
|
|
225
244
|
:param is_agentic: Whether the route is for an agentic request, defaults to False. For agentic requests
|
|
226
245
|
the selector will include a new check for `context.activity.is_agentic_request()`.
|
|
227
|
-
:type is_agentic: bool,
|
|
246
|
+
:type is_agentic: bool, Optional
|
|
228
247
|
:param rank: The rank of the route, defaults to RouteRank.DEFAULT
|
|
229
|
-
:type rank: RouteRank
|
|
248
|
+
:type rank: :class:`microsoft_agents.hosting.core.app._routes.RouteRank`, Optional
|
|
230
249
|
:param auth_handlers: A list of authentication handler IDs to use for this route, defaults to None
|
|
231
|
-
:type auth_handlers: Optional[list[str]],
|
|
250
|
+
:type auth_handlers: Optional[list[str]], Optional
|
|
232
251
|
:raises ApplicationError: If the selector or handler are not valid.
|
|
233
252
|
"""
|
|
234
253
|
if not selector or not handler:
|
|
@@ -639,9 +658,12 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
639
658
|
await self._start_long_running_call(context, self._on_turn)
|
|
640
659
|
|
|
641
660
|
async def _on_turn(self, context: TurnContext):
|
|
661
|
+
typing = None
|
|
642
662
|
try:
|
|
643
663
|
if context.activity.type != ActivityTypes.typing:
|
|
644
|
-
|
|
664
|
+
if self._options.start_typing_timer:
|
|
665
|
+
typing = TypingIndicator()
|
|
666
|
+
await typing.start(context)
|
|
645
667
|
|
|
646
668
|
self._remove_mentions(context)
|
|
647
669
|
|
|
@@ -689,11 +711,8 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
689
711
|
)
|
|
690
712
|
await self._on_error(context, err)
|
|
691
713
|
finally:
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
async def _start_typing(self, context: TurnContext):
|
|
695
|
-
if self._options.start_typing_timer:
|
|
696
|
-
await self.typing.start(context)
|
|
714
|
+
if typing:
|
|
715
|
+
await typing.stop()
|
|
697
716
|
|
|
698
717
|
def _remove_mentions(self, context: TurnContext):
|
|
699
718
|
if (
|
|
@@ -706,6 +725,11 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
706
725
|
def parse_env_vars_configuration(vars: dict[str, Any]) -> dict:
|
|
707
726
|
"""
|
|
708
727
|
Parses environment variables and returns a dictionary with the relevant configuration.
|
|
728
|
+
|
|
729
|
+
:param vars: Dictionary of environment variable names and values.
|
|
730
|
+
:type vars: dict[str, Any]
|
|
731
|
+
:return: Parsed configuration dictionary with nested structure.
|
|
732
|
+
:rtype: dict
|
|
709
733
|
"""
|
|
710
734
|
result = {}
|
|
711
735
|
for key, value in vars.items():
|
|
@@ -16,10 +16,12 @@ from microsoft_agents.hosting.core import TurnContext
|
|
|
16
16
|
class InputFile:
|
|
17
17
|
"""A file sent by the user to the bot.
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
:param content: The downloaded content of the file.
|
|
20
|
+
:type content: bytes
|
|
21
|
+
:param content_type: The content type of the file.
|
|
22
|
+
:type content_type: str
|
|
23
|
+
:param content_url: Optional. URL to the content of the file.
|
|
24
|
+
:type content_url: Optional[str]
|
|
23
25
|
"""
|
|
24
26
|
|
|
25
27
|
content: bytes
|
|
@@ -29,17 +31,19 @@ class InputFile:
|
|
|
29
31
|
|
|
30
32
|
class InputFileDownloader(ABC):
|
|
31
33
|
"""
|
|
32
|
-
|
|
34
|
+
Abstract base class for a plugin responsible for downloading files provided by the user.
|
|
35
|
+
|
|
36
|
+
Implementations should download any files referenced by the incoming activity and return a
|
|
37
|
+
list of :class:`InputFile` instances representing the downloaded content.
|
|
33
38
|
"""
|
|
34
39
|
|
|
35
40
|
@abstractmethod
|
|
36
41
|
async def download_files(self, context: TurnContext) -> List[InputFile]:
|
|
37
42
|
"""
|
|
38
|
-
Download any files
|
|
39
|
-
|
|
40
|
-
Args:
|
|
41
|
-
context (TurnContext): Context for the current turn of conversation.
|
|
43
|
+
Download any files referenced by the incoming activity for the current turn.
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
:param context: The turn context for the current request.
|
|
46
|
+
:type context: :class:`microsoft_agents.hosting.core.turn_context.TurnContext`
|
|
47
|
+
:return: A list of downloaded :class:`InputFile` objects.
|
|
48
|
+
:rtype: list[:class:`microsoft_agents.hosting.core.app.input_file.InputFile`]
|
|
45
49
|
"""
|
|
@@ -43,7 +43,7 @@ class _AuthorizationHandler(ABC):
|
|
|
43
43
|
:param connection_manager: The connection manager for OAuth providers.
|
|
44
44
|
:type connection_manager: Connections
|
|
45
45
|
:param auth_handlers: Configuration for OAuth providers.
|
|
46
|
-
:type auth_handlers: dict[str, AuthHandler],
|
|
46
|
+
:type auth_handlers: dict[str, AuthHandler], Optional
|
|
47
47
|
:raises ValueError: When storage is None or no auth handlers provided.
|
|
48
48
|
"""
|
|
49
49
|
if not storage:
|
|
@@ -75,7 +75,7 @@ class _AuthorizationHandler(ABC):
|
|
|
75
75
|
:param context: The turn context for the current turn of conversation.
|
|
76
76
|
:type context: TurnContext
|
|
77
77
|
:param scopes: Optional list of scopes to request during sign-in. If None, default scopes will be used.
|
|
78
|
-
:type scopes: Optional[list[str]],
|
|
78
|
+
:type scopes: Optional[list[str]], Optional
|
|
79
79
|
:return: A SignInResponse indicating the result of the sign-in attempt.
|
|
80
80
|
:rtype: SignInResponse
|
|
81
81
|
"""
|
|
@@ -92,9 +92,9 @@ class _AuthorizationHandler(ABC):
|
|
|
92
92
|
:param context: The turn context for the current turn of conversation.
|
|
93
93
|
:type context: TurnContext
|
|
94
94
|
:param exchange_connection: Optional name of the connection to use for token exchange. If None, default connection will be used.
|
|
95
|
-
:type exchange_connection: Optional[str],
|
|
95
|
+
:type exchange_connection: Optional[str], Optional
|
|
96
96
|
:param exchange_scopes: Optional list of scopes to request during token exchange. If None, default scopes will be used.
|
|
97
|
-
:type exchange_scopes: Optional[list[str]],
|
|
97
|
+
:type exchange_scopes: Optional[list[str]], Optional
|
|
98
98
|
"""
|
|
99
99
|
raise NotImplementedError()
|
|
100
100
|
|
|
@@ -249,9 +249,9 @@ class _UserAuthorization(_AuthorizationHandler):
|
|
|
249
249
|
:param context: The turn context for the current turn of conversation.
|
|
250
250
|
:type context: TurnContext
|
|
251
251
|
:param exchange_connection: Optional name of the connection to use for token exchange. If None, default connection will be used.
|
|
252
|
-
:type exchange_connection: Optional[str],
|
|
252
|
+
:type exchange_connection: Optional[str], Optional
|
|
253
253
|
:param exchange_scopes: Optional list of scopes to request during token exchange. If None, default scopes will be used.
|
|
254
|
-
:type exchange_scopes: Optional[list[str]],
|
|
254
|
+
:type exchange_scopes: Optional[list[str]], Optional
|
|
255
255
|
"""
|
|
256
256
|
flow, _ = await self._load_flow(context)
|
|
257
257
|
input_token_response = await flow.get_user_token()
|
|
@@ -41,7 +41,7 @@ class AgenticUserAuthorization(_AuthorizationHandler):
|
|
|
41
41
|
:param connection_manager: The connection manager for OAuth providers.
|
|
42
42
|
:type connection_manager: Connections
|
|
43
43
|
:param auth_handlers: Configuration for OAuth providers.
|
|
44
|
-
:type auth_handlers: dict[str, AuthHandler],
|
|
44
|
+
:type auth_handlers: dict[str, AuthHandler], Optional
|
|
45
45
|
:raises ValueError: When storage is None or no auth handlers provided.
|
|
46
46
|
"""
|
|
47
47
|
super().__init__(
|
|
@@ -118,20 +118,20 @@ class AgenticUserAuthorization(_AuthorizationHandler):
|
|
|
118
118
|
connection = self._connection_manager.get_token_provider(
|
|
119
119
|
context.identity, "agentic"
|
|
120
120
|
)
|
|
121
|
-
|
|
121
|
+
agentic_user_id = context.activity.get_agentic_user()
|
|
122
122
|
agentic_instance_id = context.activity.get_agentic_instance_id()
|
|
123
|
-
if not
|
|
123
|
+
if not agentic_user_id or not agentic_instance_id:
|
|
124
124
|
logger.error(
|
|
125
|
-
"Unable to retrieve agentic user token: missing
|
|
126
|
-
|
|
125
|
+
"Unable to retrieve agentic user token: missing agentic user Id or agentic instance Id. agentic_user_id: %s, Agentic Instance ID: %s",
|
|
126
|
+
agentic_user_id,
|
|
127
127
|
agentic_instance_id,
|
|
128
128
|
)
|
|
129
129
|
raise ValueError(
|
|
130
|
-
f"Unable to retrieve agentic user token: missing
|
|
130
|
+
f"Unable to retrieve agentic user token: missing agentic User Id or agentic instance Id. agentic_user_id: {agentic_user_id}, Agentic Instance ID: {agentic_instance_id}"
|
|
131
131
|
)
|
|
132
132
|
|
|
133
133
|
token = await connection.get_agentic_user_token(
|
|
134
|
-
agentic_instance_id,
|
|
134
|
+
agentic_instance_id, agentic_user_id, scopes
|
|
135
135
|
)
|
|
136
136
|
return TokenResponse(token=token) if token else TokenResponse()
|
|
137
137
|
|
|
@@ -172,9 +172,9 @@ class AgenticUserAuthorization(_AuthorizationHandler):
|
|
|
172
172
|
:param context: The turn context for the current turn of conversation.
|
|
173
173
|
:type context: TurnContext
|
|
174
174
|
:param exchange_connection: Optional name of the connection to use for token exchange. If None, default connection will be used.
|
|
175
|
-
:type exchange_connection: Optional[str],
|
|
175
|
+
:type exchange_connection: Optional[str], Optional
|
|
176
176
|
:param exchange_scopes: Optional list of scopes to request during token exchange. If None, default scopes will be used.
|
|
177
|
-
:type exchange_scopes: Optional[list[str]],
|
|
177
|
+
:type exchange_scopes: Optional[list[str]], Optional
|
|
178
178
|
"""
|
|
179
179
|
if not exchange_scopes:
|
|
180
180
|
exchange_scopes = self._handler.scopes or []
|