microsoft-agents-activity 1.2.0.dev4__py3-none-any.whl → 1.2.0.dev7__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/activity/activity.py +133 -79
- microsoft_agents/activity/config/_configure_logging.py +40 -3
- {microsoft_agents_activity-1.2.0.dev4.dist-info → microsoft_agents_activity-1.2.0.dev7.dist-info}/METADATA +1 -1
- {microsoft_agents_activity-1.2.0.dev4.dist-info → microsoft_agents_activity-1.2.0.dev7.dist-info}/RECORD +7 -7
- {microsoft_agents_activity-1.2.0.dev4.dist-info → microsoft_agents_activity-1.2.0.dev7.dist-info}/WHEEL +1 -1
- {microsoft_agents_activity-1.2.0.dev4.dist-info → microsoft_agents_activity-1.2.0.dev7.dist-info}/licenses/LICENSE +0 -0
- {microsoft_agents_activity-1.2.0.dev4.dist-info → microsoft_agents_activity-1.2.0.dev7.dist-info}/top_level.txt +0 -0
|
@@ -6,7 +6,8 @@ from __future__ import annotations
|
|
|
6
6
|
import logging
|
|
7
7
|
from copy import copy
|
|
8
8
|
from datetime import datetime, timezone
|
|
9
|
-
from typing import Optional, Any
|
|
9
|
+
from typing import Optional, Any, cast, Annotated, TypeVar
|
|
10
|
+
from typing_extensions import Self
|
|
10
11
|
|
|
11
12
|
from pydantic import (
|
|
12
13
|
Field,
|
|
@@ -48,6 +49,8 @@ from microsoft_agents.activity.errors import activity_errors
|
|
|
48
49
|
|
|
49
50
|
logger = logging.getLogger(__name__)
|
|
50
51
|
|
|
52
|
+
_EntityT = TypeVar("_EntityT", bound=Entity)
|
|
53
|
+
|
|
51
54
|
|
|
52
55
|
# TODO: A2A Agent 2 is responding with None as id, had to mark it as optional (investigate)
|
|
53
56
|
class Activity(AgentsModel, _ChannelIdFieldMixin):
|
|
@@ -157,7 +160,7 @@ class Activity(AgentsModel, _ChannelIdFieldMixin):
|
|
|
157
160
|
local_timestamp: datetime = None
|
|
158
161
|
local_timezone: NonEmptyString = None
|
|
159
162
|
service_url: NonEmptyString = None
|
|
160
|
-
from_property: ChannelAccount
|
|
163
|
+
from_property: Annotated[ChannelAccount, Field(alias="from")] = None
|
|
161
164
|
conversation: ConversationAccount = None
|
|
162
165
|
recipient: ChannelAccount = None
|
|
163
166
|
text_format: NonEmptyString = None
|
|
@@ -509,33 +512,36 @@ class Activity(AgentsModel, _ChannelIdFieldMixin):
|
|
|
509
512
|
.. remarks::
|
|
510
513
|
The new activity sets up routing information based on this activity.
|
|
511
514
|
"""
|
|
512
|
-
return
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
515
|
+
return cast(
|
|
516
|
+
Self,
|
|
517
|
+
pick_model(
|
|
518
|
+
self.__class__,
|
|
519
|
+
type=ActivityTypes.message,
|
|
520
|
+
timestamp=datetime.now(timezone.utc),
|
|
521
|
+
from_property=SkipNone(
|
|
522
|
+
ChannelAccount.pick_properties(self.recipient, ["id", "name"])
|
|
523
|
+
),
|
|
524
|
+
recipient=SkipNone(
|
|
525
|
+
ChannelAccount.pick_properties(self.from_property, ["id", "name"])
|
|
526
|
+
),
|
|
527
|
+
reply_to_id=(
|
|
528
|
+
SkipNone(self.id)
|
|
529
|
+
if self.type != ActivityTypes.conversation_update
|
|
530
|
+
or self.channel_id not in ["directline", "webchat"]
|
|
531
|
+
else None
|
|
532
|
+
),
|
|
533
|
+
service_url=self.service_url,
|
|
534
|
+
channel_id=self.channel_id,
|
|
535
|
+
conversation=SkipNone(
|
|
536
|
+
ConversationAccount.pick_properties(
|
|
537
|
+
self.conversation, ["is_group", "id", "name"]
|
|
538
|
+
)
|
|
539
|
+
),
|
|
540
|
+
text=text if text else "",
|
|
541
|
+
locale=locale if locale else SkipNone(self.locale),
|
|
542
|
+
attachments=[],
|
|
543
|
+
entities=[],
|
|
527
544
|
),
|
|
528
|
-
service_url=self.service_url,
|
|
529
|
-
channel_id=self.channel_id,
|
|
530
|
-
conversation=SkipNone(
|
|
531
|
-
ConversationAccount.pick_properties(
|
|
532
|
-
self.conversation, ["is_group", "id", "name"]
|
|
533
|
-
)
|
|
534
|
-
),
|
|
535
|
-
text=text if text else "",
|
|
536
|
-
locale=locale if locale else SkipNone(self.locale),
|
|
537
|
-
attachments=[],
|
|
538
|
-
entities=[],
|
|
539
545
|
)
|
|
540
546
|
|
|
541
547
|
def create_trace(
|
|
@@ -558,33 +564,36 @@ class Activity(AgentsModel, _ChannelIdFieldMixin):
|
|
|
558
564
|
if not value_type and value:
|
|
559
565
|
value_type = type(value).__name__
|
|
560
566
|
|
|
561
|
-
return
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
567
|
+
return cast(
|
|
568
|
+
Self,
|
|
569
|
+
pick_model(
|
|
570
|
+
self.__class__,
|
|
571
|
+
type=ActivityTypes.trace,
|
|
572
|
+
timestamp=datetime.now(timezone.utc),
|
|
573
|
+
from_property=SkipNone(
|
|
574
|
+
ChannelAccount.pick_properties(self.recipient, ["id", "name"])
|
|
575
|
+
),
|
|
576
|
+
recipient=SkipNone(
|
|
577
|
+
ChannelAccount.pick_properties(self.from_property, ["id", "name"])
|
|
578
|
+
),
|
|
579
|
+
reply_to_id=(
|
|
580
|
+
SkipNone(self.id) # preserve unset
|
|
581
|
+
if self.type != ActivityTypes.conversation_update
|
|
582
|
+
or self.channel_id not in ["directline", "webchat"]
|
|
583
|
+
else None
|
|
584
|
+
),
|
|
585
|
+
service_url=self.service_url,
|
|
586
|
+
channel_id=self.channel_id,
|
|
587
|
+
conversation=SkipNone(
|
|
588
|
+
ConversationAccount.pick_properties(
|
|
589
|
+
self.conversation, ["is_group", "id", "name"]
|
|
590
|
+
)
|
|
591
|
+
),
|
|
592
|
+
name=SkipNone(name),
|
|
593
|
+
label=SkipNone(label),
|
|
594
|
+
value_type=SkipNone(value_type),
|
|
595
|
+
value=SkipNone(value),
|
|
570
596
|
),
|
|
571
|
-
reply_to_id=(
|
|
572
|
-
SkipNone(self.id) # preserve unset
|
|
573
|
-
if type != ActivityTypes.conversation_update
|
|
574
|
-
or self.channel_id not in ["directline", "webchat"]
|
|
575
|
-
else None
|
|
576
|
-
),
|
|
577
|
-
service_url=self.service_url,
|
|
578
|
-
channel_id=self.channel_id,
|
|
579
|
-
conversation=SkipNone(
|
|
580
|
-
ConversationAccount.pick_properties(
|
|
581
|
-
self.conversation, ["is_group", "id", "name"]
|
|
582
|
-
)
|
|
583
|
-
),
|
|
584
|
-
name=SkipNone(name),
|
|
585
|
-
label=SkipNone(label),
|
|
586
|
-
value_type=SkipNone(value_type),
|
|
587
|
-
value=SkipNone(value),
|
|
588
597
|
).as_trace_activity()
|
|
589
598
|
|
|
590
599
|
@staticmethod
|
|
@@ -593,7 +602,7 @@ class Activity(AgentsModel, _ChannelIdFieldMixin):
|
|
|
593
602
|
value: object = None,
|
|
594
603
|
value_type: str | None = None,
|
|
595
604
|
label: str | None = None,
|
|
596
|
-
):
|
|
605
|
+
) -> Activity:
|
|
597
606
|
"""
|
|
598
607
|
Creates an instance of the :class:`microsoft_agents.activity.Activity` class as a TraceActivity object.
|
|
599
608
|
|
|
@@ -607,13 +616,16 @@ class Activity(AgentsModel, _ChannelIdFieldMixin):
|
|
|
607
616
|
if not value_type and value:
|
|
608
617
|
value_type = type(value).__name__
|
|
609
618
|
|
|
610
|
-
return
|
|
619
|
+
return cast(
|
|
611
620
|
Activity,
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
621
|
+
pick_model(
|
|
622
|
+
Activity,
|
|
623
|
+
type=ActivityTypes.trace,
|
|
624
|
+
name=name,
|
|
625
|
+
label=SkipNone(label),
|
|
626
|
+
value_type=SkipNone(value_type),
|
|
627
|
+
value=SkipNone(value),
|
|
628
|
+
),
|
|
617
629
|
)
|
|
618
630
|
|
|
619
631
|
@staticmethod
|
|
@@ -636,33 +648,71 @@ class Activity(AgentsModel, _ChannelIdFieldMixin):
|
|
|
636
648
|
Composite values are split only on the first ``:``.
|
|
637
649
|
:returns: A conversation reference for the conversation that contains this activity.
|
|
638
650
|
"""
|
|
639
|
-
return
|
|
651
|
+
return cast(
|
|
640
652
|
ConversationReference,
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
self.
|
|
652
|
-
|
|
653
|
-
|
|
653
|
+
pick_model(
|
|
654
|
+
ConversationReference,
|
|
655
|
+
activity_id=(
|
|
656
|
+
SkipNone(self.id)
|
|
657
|
+
if self.type != ActivityTypes.conversation_update
|
|
658
|
+
or self.channel_id not in ["directline", "webchat"]
|
|
659
|
+
else None
|
|
660
|
+
),
|
|
661
|
+
user=copy(self.from_property),
|
|
662
|
+
agent=copy(self.recipient),
|
|
663
|
+
conversation=copy(self.conversation),
|
|
664
|
+
channel_id=(
|
|
665
|
+
self.channel_id.split(":", 1)[0]
|
|
666
|
+
if force_base_channel and self.channel_id is not None
|
|
667
|
+
else self.channel_id
|
|
668
|
+
),
|
|
669
|
+
locale=self.locale,
|
|
670
|
+
service_url=self.service_url,
|
|
654
671
|
),
|
|
655
|
-
locale=self.locale,
|
|
656
|
-
service_url=self.service_url,
|
|
657
672
|
)
|
|
658
673
|
|
|
674
|
+
@staticmethod
|
|
675
|
+
def _convert_entity(raw_entity: Entity, entity_cls: type[_EntityT]) -> _EntityT:
|
|
676
|
+
"""
|
|
677
|
+
Converts an entity to a specific entity type.
|
|
678
|
+
|
|
679
|
+
:param raw_entity: The entity to convert.
|
|
680
|
+
:param entity_cls: The class of the entity type to convert to.
|
|
681
|
+
:return: The converted entity of the specified type.
|
|
682
|
+
"""
|
|
683
|
+
if isinstance(raw_entity, entity_cls):
|
|
684
|
+
return raw_entity
|
|
685
|
+
return entity_cls.model_validate(raw_entity.model_dump())
|
|
686
|
+
|
|
687
|
+
@staticmethod
|
|
688
|
+
def _convert_entity_list(
|
|
689
|
+
raw_entities: list[Entity], entity_cls: type[_EntityT]
|
|
690
|
+
) -> list[_EntityT]:
|
|
691
|
+
"""
|
|
692
|
+
Converts a list of entities to a list of a specific entity type.
|
|
693
|
+
|
|
694
|
+
:param raw_entities: The list of entities to convert.
|
|
695
|
+
:param entity_cls: The class of the entity type to convert to.
|
|
696
|
+
:return: The list of converted entities of the specified type.
|
|
697
|
+
"""
|
|
698
|
+
|
|
699
|
+
entities: list[_EntityT] = []
|
|
700
|
+
for e in raw_entities:
|
|
701
|
+
entities.append(Activity._convert_entity(e, entity_cls))
|
|
702
|
+
return entities
|
|
703
|
+
|
|
659
704
|
def get_product_info_entity(self) -> Optional[ProductInfo]:
|
|
660
705
|
if not self.entities:
|
|
661
706
|
return None
|
|
662
707
|
target = EntityTypes.PRODUCT_INFO.lower()
|
|
663
708
|
# validated entities can be Entity, and that prevents us from
|
|
664
709
|
# making assumptions about the casing of the 'type' attribute
|
|
665
|
-
|
|
710
|
+
raw_product_info = next(
|
|
711
|
+
filter(lambda e: e.type.lower() == target, self.entities), None
|
|
712
|
+
)
|
|
713
|
+
if raw_product_info is None:
|
|
714
|
+
return None
|
|
715
|
+
return Activity._convert_entity(raw_product_info, ProductInfo)
|
|
666
716
|
|
|
667
717
|
def get_mentions(self) -> list[Mention]:
|
|
668
718
|
"""
|
|
@@ -676,7 +726,11 @@ class Activity(AgentsModel, _ChannelIdFieldMixin):
|
|
|
676
726
|
"""
|
|
677
727
|
if not self.entities:
|
|
678
728
|
return []
|
|
679
|
-
|
|
729
|
+
raw_mentions = [
|
|
730
|
+
x for x in self.entities if x.type.lower() == EntityTypes.MENTION
|
|
731
|
+
]
|
|
732
|
+
|
|
733
|
+
return Activity._convert_entity_list(raw_mentions, Mention)
|
|
680
734
|
|
|
681
735
|
def get_reply_conversation_reference(
|
|
682
736
|
self, reply: ResourceResponse
|
|
@@ -20,6 +20,44 @@ _NAME_TO_LEVEL = {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
class ColorFormatter(logging.Formatter):
|
|
24
|
+
"""Logging formatter that can add ANSI color based on severity."""
|
|
25
|
+
|
|
26
|
+
MAGENTA = "\033[1;35m"
|
|
27
|
+
RED = "\033[1;31m"
|
|
28
|
+
YELLOW = "\033[1;33m"
|
|
29
|
+
GREEN = "\033[1;32m"
|
|
30
|
+
BLUE = "\033[1;34m"
|
|
31
|
+
RESET = "\033[0m"
|
|
32
|
+
|
|
33
|
+
FMT = (
|
|
34
|
+
"%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
use_colors: bool = True,
|
|
40
|
+
) -> None:
|
|
41
|
+
super().__init__(fmt=self.FMT)
|
|
42
|
+
self._plain_formatter = logging.Formatter(fmt=self.FMT)
|
|
43
|
+
if not use_colors:
|
|
44
|
+
self._formatters: dict[int, logging.Formatter] = {}
|
|
45
|
+
return
|
|
46
|
+
self._formatters = {
|
|
47
|
+
logging.CRITICAL: logging.Formatter(
|
|
48
|
+
f"{self.MAGENTA}{self.FMT}{self.RESET}"
|
|
49
|
+
),
|
|
50
|
+
logging.ERROR: logging.Formatter(f"{self.RED}{self.FMT}{self.RESET}"),
|
|
51
|
+
logging.WARNING: logging.Formatter(f"{self.YELLOW}{self.FMT}{self.RESET}"),
|
|
52
|
+
logging.INFO: logging.Formatter(f"{self.GREEN}{self.FMT}{self.RESET}"),
|
|
53
|
+
logging.DEBUG: logging.Formatter(f"{self.BLUE}{self.FMT}{self.RESET}"),
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
def format(self, record: logging.LogRecord) -> str:
|
|
57
|
+
formatter = self._formatters.get(record.levelno)
|
|
58
|
+
return (formatter or self._plain_formatter).format(record)
|
|
59
|
+
|
|
60
|
+
|
|
23
61
|
def _configure_logging(logging_config: dict):
|
|
24
62
|
"""Configures logging based on the provided logging configuration dictionary.
|
|
25
63
|
|
|
@@ -31,9 +69,7 @@ def _configure_logging(logging_config: dict):
|
|
|
31
69
|
|
|
32
70
|
console_handler = logging.StreamHandler()
|
|
33
71
|
console_handler.setFormatter(
|
|
34
|
-
|
|
35
|
-
"%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
|
|
36
|
-
)
|
|
72
|
+
ColorFormatter(use_colors=console_handler.stream.isatty())
|
|
37
73
|
)
|
|
38
74
|
|
|
39
75
|
for key in log_levels:
|
|
@@ -50,6 +86,7 @@ def _configure_logging(logging_config: dict):
|
|
|
50
86
|
else:
|
|
51
87
|
logger = logging.getLogger(namespace)
|
|
52
88
|
|
|
89
|
+
logger.propagate = False # Prevent log messages from being propagated
|
|
53
90
|
logger.handlers.clear() # Remove existing handlers to prevent duplicates
|
|
54
91
|
logger.addHandler(console_handler)
|
|
55
92
|
logger.setLevel(level)
|
|
@@ -3,7 +3,7 @@ microsoft_agents/activity/_channel_id_field_mixin.py,sha256=YRgxAiDFp8kYBVaOBUJG
|
|
|
3
3
|
microsoft_agents/activity/_model_utils.py,sha256=gUAKCOl98jA9tt95o5G7LoMuHgROvrW6lY9s0CzQu6k,2004
|
|
4
4
|
microsoft_agents/activity/_type_aliases.py,sha256=kP5tYxEKSgcgBT3bucdluVVxxopwrUaGqKL7X_TQ0Og,229
|
|
5
5
|
microsoft_agents/activity/action_types.py,sha256=nslx3hvQAd120NPdXZXdprwdjj3I3d4MWXV1b-Igr_o,419
|
|
6
|
-
microsoft_agents/activity/activity.py,sha256=
|
|
6
|
+
microsoft_agents/activity/activity.py,sha256=PvWraC7qkovJO9C-Guu90I2T7uAo7mJ5oyuB3e-o5pE,35811
|
|
7
7
|
microsoft_agents/activity/activity_event_names.py,sha256=dmtE1w50nnemTC_s1QG7IqTbnocpiczK_CG31JpgoJ4,254
|
|
8
8
|
microsoft_agents/activity/activity_importance.py,sha256=cRIlyz8EjmztPmfcgdqZ6Csp6Vp2rQhXt4ZWIDXdt_s,212
|
|
9
9
|
microsoft_agents/activity/activity_types.py,sha256=dm4vTVSoa-8_aPY_kZuU6C_FWQAURgZRassR1o8o9qQ,762
|
|
@@ -82,7 +82,7 @@ microsoft_agents/activity/video_card.py,sha256=6ZYvTYCsIsACbR3KJBhfwFJ1GTYbjKJWv
|
|
|
82
82
|
microsoft_agents/activity/_utils/__init__.py,sha256=GM-i-Cw49__7zSb7OMzS5S4KFkKU1uEf5LlINUgipmY,172
|
|
83
83
|
microsoft_agents/activity/_utils/_deferred_string.py,sha256=4FGBIExyfmncr-jxgsARWct9cy-5nnPll2nUD-UYkXw,1124
|
|
84
84
|
microsoft_agents/activity/config/__init__.py,sha256=HhYU_mkuQwpZS87JEsYmPzcWQHVRqEAdIzkKQZyvzr4,206
|
|
85
|
-
microsoft_agents/activity/config/_configure_logging.py,sha256=
|
|
85
|
+
microsoft_agents/activity/config/_configure_logging.py,sha256=oZOC9c09dNmscXzvLflLGqn950WdkvfIiVtWU173dcc,3063
|
|
86
86
|
microsoft_agents/activity/config/_load_configuration.py,sha256=u_Nrt20ZZtcONpC26jjcIJI1zGMC85oEHGVw_TmzLl0,1228
|
|
87
87
|
microsoft_agents/activity/entity/__init__.py,sha256=PGs4ZT-NclfuZbEncznR7hDxH7XROlpmL2Pw9nK_tcA,880
|
|
88
88
|
microsoft_agents/activity/entity/_schema_mixin.py,sha256=qL9uPDdxyq9Kwa8UscjxMDEQWytfmaUl6qa7Hym6nOE,1907
|
|
@@ -205,8 +205,8 @@ microsoft_agents/activity/teams/teams_member.py,sha256=vRcLRHy6wTfH7DP6k6QbrKkOR
|
|
|
205
205
|
microsoft_agents/activity/teams/teams_paged_members_result.py,sha256=jTOhoFbKPK23i-zufimB0d0_m-Lud5jQCcCHsqk2tgk,531
|
|
206
206
|
microsoft_agents/activity/teams/tenant_info.py,sha256=h8OxMd6LD5lWVj_LK2ut8z7SB0I7Gx74W1wwEiYOzXk,296
|
|
207
207
|
microsoft_agents/activity/teams/user_meeting_details.py,sha256=tvk2CWYf7Bo-DhK8NSojhanJDXEOGVrKXxJDca03CAo,467
|
|
208
|
-
microsoft_agents_activity-1.2.0.
|
|
209
|
-
microsoft_agents_activity-1.2.0.
|
|
210
|
-
microsoft_agents_activity-1.2.0.
|
|
211
|
-
microsoft_agents_activity-1.2.0.
|
|
212
|
-
microsoft_agents_activity-1.2.0.
|
|
208
|
+
microsoft_agents_activity-1.2.0.dev7.dist-info/licenses/LICENSE,sha256=ws_MuBL-SCEBqPBFl9_FqZkaaydIJmxHrJG2parhU4M,1141
|
|
209
|
+
microsoft_agents_activity-1.2.0.dev7.dist-info/METADATA,sha256=z4ZYg6Vu-Zz-eqnt8tM0juwhdpaXlrYUuxG7oETtjso,10859
|
|
210
|
+
microsoft_agents_activity-1.2.0.dev7.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
211
|
+
microsoft_agents_activity-1.2.0.dev7.dist-info/top_level.txt,sha256=lWKcT4v6fTA_NgsuHdNvuMjSrkiBMXohn64ApY7Xi8A,17
|
|
212
|
+
microsoft_agents_activity-1.2.0.dev7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|