microsoft-agents-activity 0.5.0.dev7__py3-none-any.whl → 0.5.0.dev10__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.
Potentially problematic release.
This version of microsoft-agents-activity might be problematic. Click here for more details.
- microsoft_agents/activity/__init__.py +10 -0
- microsoft_agents/activity/_channel_id_field_mixin.py +96 -0
- microsoft_agents/activity/activity.py +120 -7
- microsoft_agents/activity/channel_id.py +95 -0
- microsoft_agents/activity/conversation_reference.py +9 -3
- microsoft_agents/activity/entity/__init__.py +7 -0
- microsoft_agents/activity/entity/entity.py +1 -3
- microsoft_agents/activity/entity/entity_types.py +14 -0
- microsoft_agents/activity/entity/geo_coordinates.py +6 -3
- microsoft_agents/activity/entity/mention.py +2 -2
- microsoft_agents/activity/entity/place.py +6 -3
- microsoft_agents/activity/entity/product_info.py +20 -0
- microsoft_agents/activity/entity/thing.py +6 -3
- {microsoft_agents_activity-0.5.0.dev7.dist-info → microsoft_agents_activity-0.5.0.dev10.dist-info}/METADATA +1 -1
- {microsoft_agents_activity-0.5.0.dev7.dist-info → microsoft_agents_activity-0.5.0.dev10.dist-info}/RECORD +18 -14
- {microsoft_agents_activity-0.5.0.dev7.dist-info → microsoft_agents_activity-0.5.0.dev10.dist-info}/WHEEL +0 -0
- {microsoft_agents_activity-0.5.0.dev7.dist-info → microsoft_agents_activity-0.5.0.dev10.dist-info}/licenses/LICENSE +0 -0
- {microsoft_agents_activity-0.5.0.dev7.dist-info → microsoft_agents_activity-0.5.0.dev10.dist-info}/top_level.txt +0 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
1
4
|
from .agents_model import AgentsModel
|
|
2
5
|
from .action_types import ActionTypes
|
|
3
6
|
from .activity import Activity
|
|
@@ -17,6 +20,8 @@ from .card_action import CardAction
|
|
|
17
20
|
from .card_image import CardImage
|
|
18
21
|
from .channels import Channels
|
|
19
22
|
from .channel_account import ChannelAccount
|
|
23
|
+
from ._channel_id_field_mixin import _ChannelIdFieldMixin
|
|
24
|
+
from .channel_id import ChannelId
|
|
20
25
|
from .conversation_account import ConversationAccount
|
|
21
26
|
from .conversation_members import ConversationMembers
|
|
22
27
|
from .conversation_parameters import ConversationParameters
|
|
@@ -26,6 +31,7 @@ from .conversations_result import ConversationsResult
|
|
|
26
31
|
from .expected_replies import ExpectedReplies
|
|
27
32
|
from .entity import (
|
|
28
33
|
Entity,
|
|
34
|
+
EntityTypes,
|
|
29
35
|
AIEntity,
|
|
30
36
|
ClientCitation,
|
|
31
37
|
ClientCitationAppearance,
|
|
@@ -36,6 +42,7 @@ from .entity import (
|
|
|
36
42
|
SensitivityPattern,
|
|
37
43
|
GeoCoordinates,
|
|
38
44
|
Place,
|
|
45
|
+
ProductInfo,
|
|
39
46
|
Thing,
|
|
40
47
|
)
|
|
41
48
|
from .error import Error
|
|
@@ -115,6 +122,8 @@ __all__ = [
|
|
|
115
122
|
"CardImage",
|
|
116
123
|
"Channels",
|
|
117
124
|
"ChannelAccount",
|
|
125
|
+
"ChannelId",
|
|
126
|
+
"_ChannelIdFieldMixin",
|
|
118
127
|
"ConversationAccount",
|
|
119
128
|
"ConversationMembers",
|
|
120
129
|
"ConversationParameters",
|
|
@@ -145,6 +154,7 @@ __all__ = [
|
|
|
145
154
|
"OAuthCard",
|
|
146
155
|
"PagedMembersResult",
|
|
147
156
|
"Place",
|
|
157
|
+
"ProductInfo",
|
|
148
158
|
"ReceiptCard",
|
|
149
159
|
"ReceiptItem",
|
|
150
160
|
"ResourceResponse",
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
from typing import Optional, Any
|
|
8
|
+
|
|
9
|
+
from pydantic import (
|
|
10
|
+
ModelWrapValidatorHandler,
|
|
11
|
+
SerializerFunctionWrapHandler,
|
|
12
|
+
computed_field,
|
|
13
|
+
model_validator,
|
|
14
|
+
model_serializer,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from .channel_id import ChannelId
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# can be generalized in the future, if needed
|
|
23
|
+
class _ChannelIdFieldMixin:
|
|
24
|
+
"""A mixin to add a computed field channel_id of type ChannelId to a Pydantic model."""
|
|
25
|
+
|
|
26
|
+
_channel_id: Optional[ChannelId] = None
|
|
27
|
+
|
|
28
|
+
# required to define the setter below
|
|
29
|
+
@computed_field(return_type=Optional[ChannelId], alias="channelId")
|
|
30
|
+
@property
|
|
31
|
+
def channel_id(self) -> Optional[ChannelId]:
|
|
32
|
+
"""Gets the _channel_id field"""
|
|
33
|
+
return self._channel_id
|
|
34
|
+
|
|
35
|
+
# necessary for backward compatibility
|
|
36
|
+
# previously, channel_id was directly assigned with strings
|
|
37
|
+
@channel_id.setter
|
|
38
|
+
def channel_id(self, value: Any):
|
|
39
|
+
"""Sets the channel_id after validating it as a ChannelId model."""
|
|
40
|
+
if isinstance(value, ChannelId):
|
|
41
|
+
self._channel_id = value
|
|
42
|
+
elif isinstance(value, str):
|
|
43
|
+
self._channel_id = ChannelId(value)
|
|
44
|
+
else:
|
|
45
|
+
raise ValueError(
|
|
46
|
+
f"Invalid type for channel_id: {type(value)}. "
|
|
47
|
+
"Expected ChannelId or str."
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def _set_validated_channel_id(self, data: Any) -> None:
|
|
51
|
+
"""Sets the channel_id after validating it as a ChannelId model."""
|
|
52
|
+
if "channelId" in data:
|
|
53
|
+
self.channel_id = data["channelId"]
|
|
54
|
+
elif "channel_id" in data:
|
|
55
|
+
self.channel_id = data["channel_id"]
|
|
56
|
+
|
|
57
|
+
@model_validator(mode="wrap")
|
|
58
|
+
@classmethod
|
|
59
|
+
def _validate_channel_id(
|
|
60
|
+
cls, data: Any, handler: ModelWrapValidatorHandler
|
|
61
|
+
) -> _ChannelIdFieldMixin:
|
|
62
|
+
"""Validate the _channel_id field after model initialization.
|
|
63
|
+
|
|
64
|
+
:return: The model instance itself.
|
|
65
|
+
"""
|
|
66
|
+
try:
|
|
67
|
+
model = handler(data)
|
|
68
|
+
model._set_validated_channel_id(data)
|
|
69
|
+
return model
|
|
70
|
+
except Exception:
|
|
71
|
+
logging.error("Model %s failed to validate with data %s", cls, data)
|
|
72
|
+
raise
|
|
73
|
+
|
|
74
|
+
def _remove_serialized_unset_channel_id(
|
|
75
|
+
self, serialized: dict[str, object]
|
|
76
|
+
) -> None:
|
|
77
|
+
"""Remove the _channel_id field if it is not set."""
|
|
78
|
+
if not self._channel_id:
|
|
79
|
+
if "channelId" in serialized:
|
|
80
|
+
del serialized["channelId"]
|
|
81
|
+
elif "channel_id" in serialized:
|
|
82
|
+
del serialized["channel_id"]
|
|
83
|
+
|
|
84
|
+
@model_serializer(mode="wrap")
|
|
85
|
+
def _serialize_channel_id(
|
|
86
|
+
self, handler: SerializerFunctionWrapHandler
|
|
87
|
+
) -> dict[str, object]:
|
|
88
|
+
"""Serialize the model using Pydantic's standard serialization.
|
|
89
|
+
|
|
90
|
+
:param handler: The serialization handler provided by Pydantic.
|
|
91
|
+
:return: A dictionary representing the serialized model.
|
|
92
|
+
"""
|
|
93
|
+
serialized = handler(self)
|
|
94
|
+
if self: # serialization can be called with None
|
|
95
|
+
self._remove_serialized_unset_channel_id(serialized)
|
|
96
|
+
return serialized
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
2
|
# Licensed under the MIT License.
|
|
3
3
|
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import logging
|
|
4
7
|
from copy import copy
|
|
5
8
|
from datetime import datetime, timezone
|
|
6
|
-
from typing import Optional
|
|
7
|
-
|
|
9
|
+
from typing import Optional, Any
|
|
10
|
+
|
|
11
|
+
from pydantic import (
|
|
12
|
+
Field,
|
|
13
|
+
SerializeAsAny,
|
|
14
|
+
model_serializer,
|
|
15
|
+
model_validator,
|
|
16
|
+
SerializerFunctionWrapHandler,
|
|
17
|
+
ModelWrapValidatorHandler,
|
|
18
|
+
computed_field,
|
|
19
|
+
ValidationError,
|
|
20
|
+
)
|
|
21
|
+
|
|
8
22
|
from .activity_types import ActivityTypes
|
|
9
23
|
from .channel_account import ChannelAccount
|
|
10
24
|
from .conversation_account import ConversationAccount
|
|
@@ -14,9 +28,11 @@ from .suggested_actions import SuggestedActions
|
|
|
14
28
|
from .attachment import Attachment
|
|
15
29
|
from .entity import (
|
|
16
30
|
Entity,
|
|
31
|
+
EntityTypes,
|
|
17
32
|
Mention,
|
|
18
33
|
AIEntity,
|
|
19
34
|
ClientCitation,
|
|
35
|
+
ProductInfo,
|
|
20
36
|
SensitivityUsageInfo,
|
|
21
37
|
)
|
|
22
38
|
from .conversation_reference import ConversationReference
|
|
@@ -24,12 +40,16 @@ from .text_highlight import TextHighlight
|
|
|
24
40
|
from .semantic_action import SemanticAction
|
|
25
41
|
from .agents_model import AgentsModel
|
|
26
42
|
from .role_types import RoleTypes
|
|
43
|
+
from ._channel_id_field_mixin import _ChannelIdFieldMixin
|
|
44
|
+
from .channel_id import ChannelId
|
|
27
45
|
from ._model_utils import pick_model, SkipNone
|
|
28
46
|
from ._type_aliases import NonEmptyString
|
|
29
47
|
|
|
48
|
+
logger = logging.getLogger(__name__)
|
|
49
|
+
|
|
30
50
|
|
|
31
51
|
# TODO: A2A Agent 2 is responding with None as id, had to mark it as optional (investigate)
|
|
32
|
-
class Activity(AgentsModel):
|
|
52
|
+
class Activity(AgentsModel, _ChannelIdFieldMixin):
|
|
33
53
|
"""An Activity is the basic communication type for the protocol.
|
|
34
54
|
|
|
35
55
|
:param type: Contains the activity type. Possible values include:
|
|
@@ -50,8 +70,8 @@ class Activity(AgentsModel):
|
|
|
50
70
|
:type local_timezone: str
|
|
51
71
|
:param service_url: Contains the URL that specifies the channel's service endpoint. Set by the channel.
|
|
52
72
|
:type service_url: str
|
|
53
|
-
:param channel_id: Contains an ID that uniquely identifies the channel. Set by the channel.
|
|
54
|
-
:type channel_id:
|
|
73
|
+
:param channel_id: Contains an ID that uniquely identifies the channel (and possibly the sub-channel). Set by the channel.
|
|
74
|
+
:type channel_id: ~microsoft_agents.activity.ChannelId
|
|
55
75
|
:param from_property: Identifies the sender of the message.
|
|
56
76
|
:type from_property: ~microsoft_agents.activity.ChannelAccount
|
|
57
77
|
:param conversation: Identifies the conversation to which the activity belongs.
|
|
@@ -136,7 +156,6 @@ class Activity(AgentsModel):
|
|
|
136
156
|
local_timestamp: datetime = None
|
|
137
157
|
local_timezone: NonEmptyString = None
|
|
138
158
|
service_url: NonEmptyString = None
|
|
139
|
-
channel_id: NonEmptyString = None
|
|
140
159
|
from_property: ChannelAccount = Field(None, alias="from")
|
|
141
160
|
conversation: ConversationAccount = None
|
|
142
161
|
recipient: ChannelAccount = None
|
|
@@ -173,6 +192,92 @@ class Activity(AgentsModel):
|
|
|
173
192
|
semantic_action: SemanticAction = None
|
|
174
193
|
caller_id: NonEmptyString = None
|
|
175
194
|
|
|
195
|
+
@model_validator(mode="wrap")
|
|
196
|
+
@classmethod
|
|
197
|
+
def _validate_channel_id(
|
|
198
|
+
cls, data: Any, handler: ModelWrapValidatorHandler[Activity]
|
|
199
|
+
) -> Activity:
|
|
200
|
+
"""Validate the Activity, ensuring consistency between channel_id.sub_channel and productInfo entity.
|
|
201
|
+
|
|
202
|
+
:param data: The input data to validate.
|
|
203
|
+
:param handler: The validation handler provided by Pydantic.
|
|
204
|
+
:return: The validated Activity instance.
|
|
205
|
+
"""
|
|
206
|
+
try:
|
|
207
|
+
# run Pydantic's standard validation first
|
|
208
|
+
activity = handler(data)
|
|
209
|
+
|
|
210
|
+
# needed to assign to a computed field
|
|
211
|
+
# needed because we override the mixin validator
|
|
212
|
+
activity._set_validated_channel_id(data)
|
|
213
|
+
|
|
214
|
+
# sync sub_channel with productInfo entity
|
|
215
|
+
product_info = activity.get_product_info_entity()
|
|
216
|
+
if product_info and activity.channel_id:
|
|
217
|
+
if (
|
|
218
|
+
activity.channel_id.sub_channel
|
|
219
|
+
and activity.channel_id.sub_channel != product_info.id
|
|
220
|
+
):
|
|
221
|
+
raise Exception(
|
|
222
|
+
"Conflict between channel_id.sub_channel and productInfo entity"
|
|
223
|
+
)
|
|
224
|
+
activity.channel_id = ChannelId(
|
|
225
|
+
channel=activity.channel_id.channel,
|
|
226
|
+
sub_channel=product_info.id,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
return activity
|
|
230
|
+
except ValidationError as exc:
|
|
231
|
+
logger.error("Validation error for Activity: %s", exc, exc_info=True)
|
|
232
|
+
raise
|
|
233
|
+
|
|
234
|
+
@model_serializer(mode="wrap")
|
|
235
|
+
def _serialize_sub_channel_data(
|
|
236
|
+
self, handler: SerializerFunctionWrapHandler
|
|
237
|
+
) -> dict[str, object]:
|
|
238
|
+
"""Serialize the Activity, ensuring consistency between channel_id.sub_channel and productInfo entity.
|
|
239
|
+
|
|
240
|
+
:param handler: The serialization handler provided by Pydantic.
|
|
241
|
+
:return: A dictionary representing the serialized Activity.
|
|
242
|
+
"""
|
|
243
|
+
|
|
244
|
+
# run Pydantic's standard serialization first
|
|
245
|
+
serialized = handler(self)
|
|
246
|
+
if not self: # serialization can be called with None
|
|
247
|
+
return serialized
|
|
248
|
+
|
|
249
|
+
# find the ProductInfo entity
|
|
250
|
+
product_info = None
|
|
251
|
+
for i, entity in enumerate(serialized.get("entities") or []):
|
|
252
|
+
if entity.get("type", "") == EntityTypes.PRODUCT_INFO:
|
|
253
|
+
product_info = entity
|
|
254
|
+
break
|
|
255
|
+
|
|
256
|
+
# maintain consistency between ProductInfo entity and sub channel
|
|
257
|
+
if self.channel_id and self.channel_id.sub_channel:
|
|
258
|
+
if product_info and product_info.get("id") != self.channel_id.sub_channel:
|
|
259
|
+
raise Exception(
|
|
260
|
+
"Conflict between channel_id.sub_channel and productInfo entity"
|
|
261
|
+
)
|
|
262
|
+
elif not product_info:
|
|
263
|
+
if not serialized.get("entities"):
|
|
264
|
+
serialized["entities"] = []
|
|
265
|
+
serialized["entities"].append(
|
|
266
|
+
{
|
|
267
|
+
"type": EntityTypes.PRODUCT_INFO,
|
|
268
|
+
"id": self.channel_id.sub_channel,
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
elif product_info: # remove productInfo entity if sub_channel is not set
|
|
272
|
+
del serialized["entities"][i]
|
|
273
|
+
if not serialized["entities"]: # after removal above, list may be empty
|
|
274
|
+
del serialized["entities"]
|
|
275
|
+
|
|
276
|
+
# necessary due to computed_field serialization
|
|
277
|
+
self._remove_serialized_unset_channel_id(serialized)
|
|
278
|
+
|
|
279
|
+
return serialized
|
|
280
|
+
|
|
176
281
|
def apply_conversation_reference(
|
|
177
282
|
self, reference: ConversationReference, is_incoming: bool = False
|
|
178
283
|
):
|
|
@@ -531,6 +636,14 @@ class Activity(AgentsModel):
|
|
|
531
636
|
service_url=self.service_url,
|
|
532
637
|
)
|
|
533
638
|
|
|
639
|
+
def get_product_info_entity(self) -> Optional[ProductInfo]:
|
|
640
|
+
if not self.entities:
|
|
641
|
+
return None
|
|
642
|
+
target = EntityTypes.PRODUCT_INFO.lower()
|
|
643
|
+
# validated entities can be Entity, and that prevents us from
|
|
644
|
+
# making assumptions about the casing of the 'type' attribute
|
|
645
|
+
return next(filter(lambda e: e.type.lower() == target, self.entities), None)
|
|
646
|
+
|
|
534
647
|
def get_mentions(self) -> list[Mention]:
|
|
535
648
|
"""
|
|
536
649
|
Resolves the mentions from the entities of this activity.
|
|
@@ -543,7 +656,7 @@ class Activity(AgentsModel):
|
|
|
543
656
|
"""
|
|
544
657
|
if not self.entities:
|
|
545
658
|
return []
|
|
546
|
-
return [x for x in self.entities if x.type.lower() ==
|
|
659
|
+
return [x for x in self.entities if x.type.lower() == EntityTypes.MENTION]
|
|
547
660
|
|
|
548
661
|
def get_reply_conversation_reference(
|
|
549
662
|
self, reply: ResourceResponse
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from typing import Optional, Any
|
|
7
|
+
|
|
8
|
+
from pydantic_core import CoreSchema, core_schema
|
|
9
|
+
from pydantic import GetCoreSchemaHandler
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ChannelId(str):
|
|
13
|
+
"""A ChannelId represents a channel and optional sub-channel in the format 'channel:sub_channel'."""
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
value: Optional[str] = None,
|
|
18
|
+
*,
|
|
19
|
+
channel: Optional[str] = None,
|
|
20
|
+
sub_channel: Optional[str] = None,
|
|
21
|
+
) -> None:
|
|
22
|
+
"""Initialize a ChannelId instance.
|
|
23
|
+
|
|
24
|
+
:param value: The full channel ID string in the format 'channel:sub_channel'. Must be provided if channel is not provided.
|
|
25
|
+
:param channel: The main channel string. Must be provided if value is not provided.
|
|
26
|
+
:param sub_channel: The sub-channel string.
|
|
27
|
+
:raises ValueError: If the input parameters are invalid. value and channel cannot both be provided.
|
|
28
|
+
"""
|
|
29
|
+
super().__init__()
|
|
30
|
+
if not channel:
|
|
31
|
+
split = self.strip().split(":", 1)
|
|
32
|
+
self._channel = split[0].strip()
|
|
33
|
+
self._sub_channel = split[1].strip() if len(split) == 2 else None
|
|
34
|
+
else:
|
|
35
|
+
self._channel = channel
|
|
36
|
+
self._sub_channel = sub_channel
|
|
37
|
+
|
|
38
|
+
def __new__(
|
|
39
|
+
cls,
|
|
40
|
+
value: Optional[str] = None,
|
|
41
|
+
*,
|
|
42
|
+
channel: Optional[str] = None,
|
|
43
|
+
sub_channel: Optional[str] = None,
|
|
44
|
+
) -> ChannelId:
|
|
45
|
+
"""Create a new ChannelId instance.
|
|
46
|
+
|
|
47
|
+
:param value: The full channel ID string in the format 'channel:sub_channel'. Must be provided if channel is not provided.
|
|
48
|
+
:param channel: The main channel string. Must be provided if value is not provided. Must not contain ':', as it delimits channels and sub channels.
|
|
49
|
+
:param sub_channel: The sub-channel string.
|
|
50
|
+
:return: A new ChannelId instance.
|
|
51
|
+
:raises ValueError: If the input parameters are invalid. value and channel cannot both be provided.
|
|
52
|
+
"""
|
|
53
|
+
if isinstance(value, str):
|
|
54
|
+
if channel or sub_channel:
|
|
55
|
+
raise ValueError(
|
|
56
|
+
"If value is provided, channel and sub_channel must be None"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
value = value.strip()
|
|
60
|
+
if value:
|
|
61
|
+
return str.__new__(cls, value)
|
|
62
|
+
raise TypeError("value must be a non empty string if provided")
|
|
63
|
+
else:
|
|
64
|
+
if (
|
|
65
|
+
not isinstance(channel, str)
|
|
66
|
+
or len(channel.strip()) == 0
|
|
67
|
+
or ":" in channel
|
|
68
|
+
):
|
|
69
|
+
raise TypeError(
|
|
70
|
+
"channel must be a non empty string, and must not contain the ':' character"
|
|
71
|
+
)
|
|
72
|
+
if sub_channel is not None and (not isinstance(sub_channel, str)):
|
|
73
|
+
raise TypeError("sub_channel must be a string if provided")
|
|
74
|
+
channel = channel.strip()
|
|
75
|
+
sub_channel = sub_channel.strip() if sub_channel else None
|
|
76
|
+
if sub_channel:
|
|
77
|
+
return str.__new__(cls, f"{channel}:{sub_channel}")
|
|
78
|
+
return str.__new__(cls, channel)
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def channel(self) -> str:
|
|
82
|
+
"""The main channel, e.g. 'email' in 'email:work'."""
|
|
83
|
+
return self._channel # type: ignore[return-value]
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def sub_channel(self) -> Optional[str]:
|
|
87
|
+
"""The sub-channel, e.g. 'work' in 'email:work'. May be None."""
|
|
88
|
+
return self._sub_channel
|
|
89
|
+
|
|
90
|
+
# https://docs.pydantic.dev/dev/concepts/types/#customizing-validation-with-__get_pydantic_core_schema__
|
|
91
|
+
@classmethod
|
|
92
|
+
def __get_pydantic_core_schema__(
|
|
93
|
+
cls, source_type: Any, handler: GetCoreSchemaHandler
|
|
94
|
+
) -> CoreSchema:
|
|
95
|
+
return core_schema.no_info_after_validator_function(cls, handler(str))
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
2
|
# Licensed under the MIT License.
|
|
3
3
|
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
4
6
|
from uuid import uuid4 as uuid
|
|
5
7
|
from typing import Optional
|
|
8
|
+
import logging
|
|
6
9
|
|
|
7
10
|
from pydantic import Field
|
|
8
11
|
|
|
9
12
|
from .channel_account import ChannelAccount
|
|
13
|
+
from ._channel_id_field_mixin import _ChannelIdFieldMixin
|
|
14
|
+
from .channel_id import ChannelId
|
|
10
15
|
from .conversation_account import ConversationAccount
|
|
11
16
|
from .agents_model import AgentsModel
|
|
12
17
|
from ._type_aliases import NonEmptyString
|
|
13
18
|
from .activity_types import ActivityTypes
|
|
14
19
|
from .activity_event_names import ActivityEventNames
|
|
15
20
|
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
16
23
|
|
|
17
|
-
class ConversationReference(AgentsModel):
|
|
24
|
+
class ConversationReference(AgentsModel, _ChannelIdFieldMixin):
|
|
18
25
|
"""An object relating to a particular point in a conversation.
|
|
19
26
|
|
|
20
27
|
:param activity_id: (Optional) ID of the activity to refer to
|
|
@@ -26,7 +33,7 @@ class ConversationReference(AgentsModel):
|
|
|
26
33
|
:param conversation: Conversation reference
|
|
27
34
|
:type conversation: ~microsoft_agents.activity.ConversationAccount
|
|
28
35
|
:param channel_id: Channel ID
|
|
29
|
-
:type channel_id:
|
|
36
|
+
:type channel_id: ~microsoft_agents.activity.ChannelId
|
|
30
37
|
:param locale: A locale name for the contents of the text field.
|
|
31
38
|
The locale name is a combination of an ISO 639 two- or three-letter
|
|
32
39
|
culture code associated with a language and an ISO 3166 two-letter
|
|
@@ -43,7 +50,6 @@ class ConversationReference(AgentsModel):
|
|
|
43
50
|
user: Optional[ChannelAccount] = None
|
|
44
51
|
agent: ChannelAccount = Field(None, alias="bot")
|
|
45
52
|
conversation: ConversationAccount
|
|
46
|
-
channel_id: NonEmptyString
|
|
47
53
|
locale: Optional[NonEmptyString] = None
|
|
48
54
|
service_url: NonEmptyString = None
|
|
49
55
|
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
1
4
|
from .mention import Mention
|
|
2
5
|
from .entity import Entity
|
|
6
|
+
from .entity_types import EntityTypes
|
|
3
7
|
from .ai_entity import (
|
|
4
8
|
ClientCitation,
|
|
5
9
|
ClientCitationAppearance,
|
|
@@ -11,10 +15,12 @@ from .ai_entity import (
|
|
|
11
15
|
)
|
|
12
16
|
from .geo_coordinates import GeoCoordinates
|
|
13
17
|
from .place import Place
|
|
18
|
+
from .product_info import ProductInfo
|
|
14
19
|
from .thing import Thing
|
|
15
20
|
|
|
16
21
|
__all__ = [
|
|
17
22
|
"Entity",
|
|
23
|
+
"EntityTypes",
|
|
18
24
|
"AIEntity",
|
|
19
25
|
"ClientCitation",
|
|
20
26
|
"ClientCitationAppearance",
|
|
@@ -25,5 +31,6 @@ __all__ = [
|
|
|
25
31
|
"SensitivityPattern",
|
|
26
32
|
"GeoCoordinates",
|
|
27
33
|
"Place",
|
|
34
|
+
"ProductInfo",
|
|
28
35
|
"Thing",
|
|
29
36
|
]
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
2
|
# Licensed under the MIT License.
|
|
3
3
|
|
|
4
|
-
from typing import Any
|
|
5
|
-
from enum import Enum
|
|
4
|
+
from typing import Any
|
|
6
5
|
|
|
7
6
|
from pydantic import model_serializer, model_validator
|
|
8
7
|
from pydantic.alias_generators import to_camel, to_snake
|
|
9
8
|
|
|
10
9
|
from ..agents_model import AgentsModel, ConfigDict
|
|
11
|
-
from .._type_aliases import NonEmptyString
|
|
12
10
|
|
|
13
11
|
|
|
14
12
|
class Entity(AgentsModel):
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class EntityTypes(str, Enum):
|
|
8
|
+
"""Well-known enumeration of entity types."""
|
|
9
|
+
|
|
10
|
+
GEO_COORDINATES = "GeoCoordinates"
|
|
11
|
+
MENTION = "mention"
|
|
12
|
+
PLACE = "Place"
|
|
13
|
+
THING = "Thing"
|
|
14
|
+
PRODUCT_INFO = "ProductInfo"
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
2
|
# Licensed under the MIT License.
|
|
3
3
|
|
|
4
|
-
from
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
5
6
|
from .._type_aliases import NonEmptyString
|
|
7
|
+
from .entity import Entity
|
|
8
|
+
from .entity_types import EntityTypes
|
|
6
9
|
|
|
7
10
|
|
|
8
|
-
class GeoCoordinates(
|
|
11
|
+
class GeoCoordinates(Entity):
|
|
9
12
|
"""GeoCoordinates (entity type: "https://schema.org/GeoCoordinates").
|
|
10
13
|
|
|
11
14
|
:param elevation: Elevation of the location [WGS
|
|
@@ -26,5 +29,5 @@ class GeoCoordinates(AgentsModel):
|
|
|
26
29
|
elevation: float = None
|
|
27
30
|
latitude: float = None
|
|
28
31
|
longitude: float = None
|
|
29
|
-
type:
|
|
32
|
+
type: Literal[EntityTypes.GEO_COORDINATES] = EntityTypes.GEO_COORDINATES
|
|
30
33
|
name: NonEmptyString = None
|
|
@@ -5,7 +5,7 @@ from typing import Literal
|
|
|
5
5
|
|
|
6
6
|
from ..channel_account import ChannelAccount
|
|
7
7
|
from .entity import Entity
|
|
8
|
-
from
|
|
8
|
+
from .entity_types import EntityTypes
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Mention(Entity):
|
|
@@ -21,4 +21,4 @@ class Mention(Entity):
|
|
|
21
21
|
|
|
22
22
|
mentioned: ChannelAccount = None
|
|
23
23
|
text: str = None
|
|
24
|
-
type: Literal[
|
|
24
|
+
type: Literal[EntityTypes.MENTION] = EntityTypes.MENTION
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
2
|
# Licensed under the MIT License.
|
|
3
3
|
|
|
4
|
-
from
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
5
6
|
from .._type_aliases import NonEmptyString
|
|
7
|
+
from .entity import Entity
|
|
8
|
+
from .entity_types import EntityTypes
|
|
6
9
|
|
|
7
10
|
|
|
8
|
-
class Place(
|
|
11
|
+
class Place(Entity):
|
|
9
12
|
"""Place (entity type: "https://schema.org/Place").
|
|
10
13
|
|
|
11
14
|
:param address: Address of the place (may be `string` or complex object of
|
|
@@ -26,5 +29,5 @@ class Place(AgentsModel):
|
|
|
26
29
|
address: object = None
|
|
27
30
|
geo: object = None
|
|
28
31
|
has_map: object = None
|
|
29
|
-
type:
|
|
32
|
+
type: Literal[EntityTypes.PLACE] = EntityTypes.PLACE
|
|
30
33
|
name: NonEmptyString = None
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
from .entity import Entity
|
|
7
|
+
from .entity_types import EntityTypes
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ProductInfo(Entity):
|
|
11
|
+
"""Product information (entity type: "productInfo").
|
|
12
|
+
|
|
13
|
+
:param type: The type of the entity, always "productInfo".
|
|
14
|
+
:type type: str
|
|
15
|
+
:param id: The unique identifier for the product.
|
|
16
|
+
:type id: str
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
type: Literal[EntityTypes.PRODUCT_INFO] = EntityTypes.PRODUCT_INFO
|
|
20
|
+
id: str = None
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
2
|
# Licensed under the MIT License.
|
|
3
3
|
|
|
4
|
-
from
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
5
6
|
from .._type_aliases import NonEmptyString
|
|
7
|
+
from .entity import Entity
|
|
8
|
+
from .entity_types import EntityTypes
|
|
6
9
|
|
|
7
10
|
|
|
8
|
-
class Thing(
|
|
11
|
+
class Thing(Entity):
|
|
9
12
|
"""Thing (entity type: "https://schema.org/Thing").
|
|
10
13
|
|
|
11
14
|
:param type: The type of the thing
|
|
@@ -14,5 +17,5 @@ class Thing(AgentsModel):
|
|
|
14
17
|
:type name: str
|
|
15
18
|
"""
|
|
16
19
|
|
|
17
|
-
type:
|
|
20
|
+
type: Literal[EntityTypes.THING] = EntityTypes.THING
|
|
18
21
|
name: NonEmptyString = None
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
microsoft_agents/activity/__init__.py,sha256=
|
|
1
|
+
microsoft_agents/activity/__init__.py,sha256=BYUTF2A_YEw5Ql_hPS7MLBGEsmvey6vrMGh9hpsB7EA,6378
|
|
2
|
+
microsoft_agents/activity/_channel_id_field_mixin.py,sha256=pFMfbN5EVrhO-7mFE-_8kT3yZ1zS6s9jyXoDGTLHT7g,3222
|
|
2
3
|
microsoft_agents/activity/_load_configuration.py,sha256=ztmv1wOBDE9hUYPPzWexc-qi0eiBmxnay1skJpKVEcY,1125
|
|
3
4
|
microsoft_agents/activity/_model_utils.py,sha256=gUAKCOl98jA9tt95o5G7LoMuHgROvrW6lY9s0CzQu6k,2004
|
|
4
5
|
microsoft_agents/activity/_type_aliases.py,sha256=kP5tYxEKSgcgBT3bucdluVVxxopwrUaGqKL7X_TQ0Og,229
|
|
5
6
|
microsoft_agents/activity/action_types.py,sha256=nslx3hvQAd120NPdXZXdprwdjj3I3d4MWXV1b-Igr_o,419
|
|
6
|
-
microsoft_agents/activity/activity.py,sha256=
|
|
7
|
+
microsoft_agents/activity/activity.py,sha256=fOzNz7wVmgWcbEt2nomXEezshwmiNYQEo64z9kUJM2c,32377
|
|
7
8
|
microsoft_agents/activity/activity_event_names.py,sha256=dmtE1w50nnemTC_s1QG7IqTbnocpiczK_CG31JpgoJ4,254
|
|
8
9
|
microsoft_agents/activity/activity_importance.py,sha256=cRIlyz8EjmztPmfcgdqZ6Csp6Vp2rQhXt4ZWIDXdt_s,212
|
|
9
10
|
microsoft_agents/activity/activity_types.py,sha256=dm4vTVSoa-8_aPY_kZuU6C_FWQAURgZRassR1o8o9qQ,762
|
|
@@ -24,12 +25,13 @@ microsoft_agents/activity/card_action.py,sha256=-c9VLUNVrRx1wYCSiCueZRvWOO5nWOA6
|
|
|
24
25
|
microsoft_agents/activity/card_image.py,sha256=2DCOErbmGm8dRhJrYhxDweQgH0ys-5_cRISxgJ7hx9k,640
|
|
25
26
|
microsoft_agents/activity/channel_account.py,sha256=2M5K1NJl1GTttYNI65OQBvxLcgGzx9B7bJhjdTHRsgo,1217
|
|
26
27
|
microsoft_agents/activity/channel_adapter_protocol.py,sha256=CQU9FhsR5UCzRib8DJVj9DO0131QB9Kn5euhHRKGCf4,2135
|
|
28
|
+
microsoft_agents/activity/channel_id.py,sha256=m59mGBfHQ5g3AdK2p_kMxIm9pC--okgOz3wopTmxFMs,3814
|
|
27
29
|
microsoft_agents/activity/channels.py,sha256=UC5MDF5C4PbW29rJhtXzfjA-4y4VqPXi1nK8oCmHM0o,4560
|
|
28
30
|
microsoft_agents/activity/contact_relation_update_action_types.py,sha256=6RIJbnVmr8agTPYYw84xTH9rx88QE0dvMbNwC0cpcG0,208
|
|
29
31
|
microsoft_agents/activity/conversation_account.py,sha256=fOU9PgxnH8NsHIZDiESU22Ph3oEE0PMnLbKYuz3vgYA,1536
|
|
30
32
|
microsoft_agents/activity/conversation_members.py,sha256=6-kBKO3W7rtpG1sbhKX5T6FDBDlQDzXdIIpjQALw1K4,552
|
|
31
33
|
microsoft_agents/activity/conversation_parameters.py,sha256=JwsoZeml90q8W_ngYBao218-q1FIMSAbIf3yUXz3yAg,1475
|
|
32
|
-
microsoft_agents/activity/conversation_reference.py,sha256=
|
|
34
|
+
microsoft_agents/activity/conversation_reference.py,sha256=hcWDW8oi18KDX4HCcMfEOcsa9IJgj-_ymXPbg49LGsY,2657
|
|
33
35
|
microsoft_agents/activity/conversation_resource_response.py,sha256=du_lE0AFPo_PEWj2a5gilsYFD8wfDidPh9LmUHQJVyA,652
|
|
34
36
|
microsoft_agents/activity/conversation_update_types.py,sha256=l57bE-oXKEYyrTLPmcYCioZD_VSfXQLUl9l29Pkw_7w,568
|
|
35
37
|
microsoft_agents/activity/conversations_result.py,sha256=GK_l5ou-veMnM7eQgiTQ1eUnf52KKEi6okUzf_ybeNc,617
|
|
@@ -78,13 +80,15 @@ microsoft_agents/activity/token_status.py,sha256=o3pGTKRjuqEndRWClMe91Cmox6cW8aD
|
|
|
78
80
|
microsoft_agents/activity/transcript.py,sha256=vV0p-JEt62UPp3D4gmz1Fn1vq45vpjc01x2p5iCzKsw,423
|
|
79
81
|
microsoft_agents/activity/turn_context_protocol.py,sha256=S1lJi_pT-o3w0RNB9p4WDiOEL7SHBf_gojRfY9CBwF4,1787
|
|
80
82
|
microsoft_agents/activity/video_card.py,sha256=6ZYvTYCsIsACbR3KJBhfwFJ1GTYbjKJWvBsqw0pyyWA,2048
|
|
81
|
-
microsoft_agents/activity/entity/__init__.py,sha256=
|
|
83
|
+
microsoft_agents/activity/entity/__init__.py,sha256=nq9ySwflvNeFWKxZmvb4XenYwB_ATDbeOikkk860UfY,826
|
|
82
84
|
microsoft_agents/activity/entity/ai_entity.py,sha256=VOjU9Y6m68vkiKUHnqG5XmNPRu4KCSKmd0XPDCJ6B0s,3280
|
|
83
|
-
microsoft_agents/activity/entity/entity.py,sha256=
|
|
84
|
-
microsoft_agents/activity/entity/
|
|
85
|
-
microsoft_agents/activity/entity/
|
|
86
|
-
microsoft_agents/activity/entity/
|
|
87
|
-
microsoft_agents/activity/entity/
|
|
85
|
+
microsoft_agents/activity/entity/entity.py,sha256=FmJ23emzoEiV66JjpkOwCQoJReFB_5whihj3PFdRtKk,1105
|
|
86
|
+
microsoft_agents/activity/entity/entity_types.py,sha256=_oqG6O2Ds0BHmY65KN_elaXly6rporMmUYcaWEjqi3s,336
|
|
87
|
+
microsoft_agents/activity/entity/geo_coordinates.py,sha256=xLc8SGGmjmJL3m-ionTicC_rL4x09_0hWa28Ed5JKLs,1080
|
|
88
|
+
microsoft_agents/activity/entity/mention.py,sha256=Gpjy4o7_5EQ1flkADPMzJw6nOU92uzf5Gt54Rj7Oi-c,714
|
|
89
|
+
microsoft_agents/activity/entity/place.py,sha256=uw-YUdbhkgawjor92vZwz7qmdcSIVDhYG0L5CphfFrI,995
|
|
90
|
+
microsoft_agents/activity/entity/product_info.py,sha256=bFacwylgKbLuebM5zVpMyud32SCvH6_pJ4n6_wWYMdg,529
|
|
91
|
+
microsoft_agents/activity/entity/thing.py,sha256=u-uWCHgZrrjh_d7pje1GszNmiDfLRKbM26PJnel8Ye8,527
|
|
88
92
|
microsoft_agents/activity/teams/__init__.py,sha256=pdcnd_Ud92Eox_fHSgm1kwzwFmG8LVeatF9MRI8IaVY,8532
|
|
89
93
|
microsoft_agents/activity/teams/app_based_link_query.py,sha256=-2uuPbyElN0DbU5R_mTJ_o7jphBNFr1ZFlLeziXuxn0,462
|
|
90
94
|
microsoft_agents/activity/teams/batch_failed_entries_response.py,sha256=Q6Mgbdu_OdFGEKmaMu3jr71BSfwNtAgCMLyDSrfLf7I,439
|
|
@@ -192,8 +196,8 @@ microsoft_agents/activity/teams/teams_member.py,sha256=vRcLRHy6wTfH7DP6k6QbrKkOR
|
|
|
192
196
|
microsoft_agents/activity/teams/teams_paged_members_result.py,sha256=cG4eKHjA0u1EMioC2ErVpydnoPJrtTDcdhdzYET9xto,555
|
|
193
197
|
microsoft_agents/activity/teams/tenant_info.py,sha256=h8OxMd6LD5lWVj_LK2ut8z7SB0I7Gx74W1wwEiYOzXk,296
|
|
194
198
|
microsoft_agents/activity/teams/user_meeting_details.py,sha256=tvk2CWYf7Bo-DhK8NSojhanJDXEOGVrKXxJDca03CAo,467
|
|
195
|
-
microsoft_agents_activity-0.5.0.
|
|
196
|
-
microsoft_agents_activity-0.5.0.
|
|
197
|
-
microsoft_agents_activity-0.5.0.
|
|
198
|
-
microsoft_agents_activity-0.5.0.
|
|
199
|
-
microsoft_agents_activity-0.5.0.
|
|
199
|
+
microsoft_agents_activity-0.5.0.dev10.dist-info/licenses/LICENSE,sha256=ws_MuBL-SCEBqPBFl9_FqZkaaydIJmxHrJG2parhU4M,1141
|
|
200
|
+
microsoft_agents_activity-0.5.0.dev10.dist-info/METADATA,sha256=p9kymyEI4VhcE2XdeZJsbUVe0v4aDMmVBKMQNPKkXHU,8071
|
|
201
|
+
microsoft_agents_activity-0.5.0.dev10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
202
|
+
microsoft_agents_activity-0.5.0.dev10.dist-info/top_level.txt,sha256=lWKcT4v6fTA_NgsuHdNvuMjSrkiBMXohn64ApY7Xi8A,17
|
|
203
|
+
microsoft_agents_activity-0.5.0.dev10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|