Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from .action_types import ActionTypes
from .activity import Activity
from .activity_event_names import ActivityEventNames
from .activity_treatment import ActivityTreatment, ActivityTreatmentType
from .activity_types import ActivityTypes
from .adaptive_card_invoke_action import AdaptiveCardInvokeAction
from .adaptive_card_invoke_response import AdaptiveCardInvokeResponse
Expand All @@ -24,7 +25,7 @@
from .conversation_resource_response import ConversationResourceResponse
from .conversations_result import ConversationsResult
from .expected_replies import ExpectedReplies
from .entity import Entity
from .entity import Entity, EntityTypes
from .ai_entity import (
AIEntity,
ClientCitation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Optional
from pydantic import Field, SerializeAsAny
from .activity_types import ActivityTypes
from .activity_treatment import ActivityTreatment
from .channel_account import ChannelAccount
from .conversation_account import ConversationAccount
from .mention import Mention
Expand Down Expand Up @@ -532,8 +533,15 @@ def get_mentions(self) -> list[Mention]:
This method is defined on the :class:`Activity` class, but is only intended for use with a message activity,
where the activity Activity.Type is set to ActivityTypes.Message.
"""
_list = self.entities
return [x for x in _list if str(x.type).lower() == "mention"]
return [x for x in self.entities if str(x.type).lower() == "mention"]

def get_activity_treatments(self) -> list[ActivityTreatment]:
"""
Resolves the activity treatments from the entities of this activity.

:returns: The array of activity treatments; or an empty array, if none are found.
"""
return [x for x in self.entities if str(x.type).lower() == "activitytreatment"]

def get_reply_conversation_reference(
self, reply: ResourceResponse
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from enum import Enum

from .entity import Entity, EntityTypes
from ._type_aliases import NonEmptyString


class ActivityTreatmentType(str, Enum):
"""Activity treatment types

TARGETED: only the recipient should be able to see the message even if the activity
is being sent to a group of people.
"""

TARGETED = "targeted"


class ActivityTreatment(Entity):
"""Activity treatment information (entity type: "activitytreatment").

:param treatment: The treatment type
:type treatment: ~microsoft.agents.activity.ActivityTreatmentType
:param type: Type of this entity (RFC 3987 IRI)
:type type: NonEmptyString
"""

treatment: ActivityTreatmentType = None
type: NonEmptyString = EntityTypes.ACTIVITY_TREATMENT
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
from __future__ import annotations

from typing import Any, Optional

from pydantic import model_serializer, model_validator
from .agents_model import AgentsModel, ConfigDict
from pydantic.alias_generators import to_camel, to_snake
from ._type_aliases import NonEmptyString

from enum import Enum


class EntityTypes:

MENTION = "mention"
ACTIVITY_TREATMENT = "activitytreatment"

# ENTITY_MAP = {
# EntityTypes.MENTION: Mention,
# EntityTypes.ACTIVITY_TREATMENT: ActivityTreatment,
# }


class Entity(AgentsModel):
"""Metadata object pertaining to an activity.
Expand Down Expand Up @@ -36,3 +51,7 @@ def to_camel_for_all(self, config):
new_data[to_camel(k)] = v
return new_data
return {k: v for k, v in self}

# @classmethod
# def deserialize_entity(cls, entity: Entity) -> Entity:
# return EntityTypes.ENTITY_MAP[entity.type](entity.model_dump())
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .channel_account import ChannelAccount
from .entity import Entity
from .entity import Entity, EntityTypes
from ._type_aliases import NonEmptyString


Expand All @@ -16,4 +16,4 @@ class Mention(Entity):

mentioned: ChannelAccount = None
text: NonEmptyString = None
type: NonEmptyString = None
type: NonEmptyString = EntityTypes.MENTION
59 changes: 59 additions & 0 deletions libraries/microsoft-agents-activity/tests/test_activity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import pytest

from microsoft.agents.activity import (
Activity,
ActivityTreatment,
ActivityTreatmentType,
Entity,
EntityTypes,
Mention,
)


class TestActivityGetEntities:

@pytest.fixture
def activity(self):
return Activity(
type="message",
entities=[
ActivityTreatment(treatment=ActivityTreatmentType.TARGETED),
Entity(
type=EntityTypes.ACTIVITY_TREATMENT,
treatment=ActivityTreatmentType.TARGETED,
),
Mention(type=EntityTypes.MENTION, text="Hello"),
Entity(type=EntityTypes.MENTION),
Entity(type=EntityTypes.ACTIVITY_TREATMENT, treatment=None),
],
)

def test_activity_get_mentions(self, activity):
expected = [
Mention(type=EntityTypes.MENTION, text="Hello"),
Entity(type=EntityTypes.MENTION),
]
ret = activity.get_mentions()
assert activity.get_mentions() == expected
assert ret[0].text == "Hello"
assert ret[0].type == EntityTypes.MENTION
assert not hasattr(ret[1], "text")
assert ret[1].type == EntityTypes.MENTION

def test_activity_get_activity_treatments(self, activity):
expected = [
ActivityTreatment(treatment=ActivityTreatmentType.TARGETED),
Entity(
type=EntityTypes.ACTIVITY_TREATMENT,
treatment=ActivityTreatmentType.TARGETED,
),
Entity(type=EntityTypes.ACTIVITY_TREATMENT, treatment=None),
]
ret = activity.get_activity_treatments()
assert ret == expected
assert ret[0].treatment == ActivityTreatmentType.TARGETED
assert ret[0].type == EntityTypes.ACTIVITY_TREATMENT
assert ret[1].treatment == ActivityTreatmentType.TARGETED
assert ret[1].type == EntityTypes.ACTIVITY_TREATMENT
assert ret[2].treatment is None
assert ret[2].type == EntityTypes.ACTIVITY_TREATMENT
75 changes: 75 additions & 0 deletions libraries/microsoft-agents-activity/tests/test_entities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import pytest

from microsoft.agents.activity import (
Entity,
EntityTypes,
Mention,
ActivityTreatment,
ActivityTreatmentType,
ChannelAccount,
)


class TestSerialization:

def test_mention_serializer(self):
initial_mention = Mention(text="Hello", mentioned=ChannelAccount(id="abc"))
initial_mention_dict = initial_mention.model_dump(
mode="json", exclude_unset=True, by_alias=True
)
mention = Mention.model_validate(initial_mention_dict)

assert initial_mention_dict == {
"text": "Hello",
"mentioned": {"id": "abc"},
"type": EntityTypes.MENTION,
}
assert mention == initial_mention

def test_mention_serializer_as_entity(self):
initial_mention = Entity(
text="Hello", mentioned=ChannelAccount(id="abc"), type=EntityTypes.MENTION
)
initial_mention_dict = initial_mention.model_dump(
mode="json", exclude_unset=True, by_alias=True
)
mention = Mention.model_validate(initial_mention_dict)

assert initial_mention_dict == {
"text": "Hello",
"mentioned": {"id": "abc"},
"type": EntityTypes.MENTION,
}
assert mention.type == initial_mention.type
assert mention.text == initial_mention.text
assert mention.mentioned == initial_mention.mentioned

def test_activity_treatment_serializer(self):
initial_treatment = ActivityTreatment(treatment=ActivityTreatmentType.TARGETED)
initial_treatment_dict = initial_treatment.model_dump(
mode="json", exclude_unset=True, by_alias=True
)
treatment = ActivityTreatment.model_validate(initial_treatment_dict)

assert initial_treatment_dict == {
"treatment": ActivityTreatmentType.TARGETED,
"type": EntityTypes.ACTIVITY_TREATMENT,
}
assert treatment == initial_treatment

def test_activity_treatment_serializer_as_entity(self):
initial_treatment = Entity(
treatment=ActivityTreatmentType.TARGETED,
type=EntityTypes.ACTIVITY_TREATMENT,
)
initial_treatment_dict = initial_treatment.model_dump(
mode="json", exclude_unset=True, by_alias=True
)
treatment = ActivityTreatment.model_validate(initial_treatment_dict)

assert initial_treatment_dict == {
"treatment": ActivityTreatmentType.TARGETED,
"type": EntityTypes.ACTIVITY_TREATMENT,
}
assert treatment.type == initial_treatment.type
assert treatment.treatment == initial_treatment.treatment