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
4 changes: 2 additions & 2 deletions packages/api/src/microsoft_teams/api/activities/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pydantic import Field, TypeAdapter

from . import event, install_update, invoke, message
from .activity_params import ActivityParams
from .sendable_activity import SendableActivity
from .command import CommandActivity, CommandResultActivity, CommandResultValue, CommandSendActivity, CommandSendValue
from .conversation import (
ConversationActivity,
Expand Down Expand Up @@ -68,7 +68,7 @@
"ConversationEventType",
"InvokeActivity",
"TraceActivity",
"ActivityParams",
"SendableActivity",
"SentActivity",
]
__all__.extend(event.__all__)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
)
from .typing import TypingActivityInput

ActivityParams = Annotated[
SendableActivity = Annotated[
Union[
MessageActivityInput,
MessageReactionActivityInput,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""

from ..models import CustomBaseModel
from . import ActivityParams
from . import SendableActivity
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sent_activity.py imports SendableActivity via from . import SendableActivity, which relies on package __init__.py import ordering and makes the module harder to reuse independently. Prefer importing SendableActivity directly from .sendable_activity to remove the implicit dependency.

Suggested change
from . import SendableActivity
from .sendable_activity import SendableActivity

Copilot uses AI. Check for mistakes.


class SentActivity(CustomBaseModel):
Expand All @@ -13,10 +13,10 @@ class SentActivity(CustomBaseModel):
id: str
"""Id of the activity."""

activity_params: ActivityParams
activity_params: SendableActivity
"""Additional parameters for the activity."""

@classmethod
def merge(cls, activity_params: ActivityParams, curr_activity: "SentActivity") -> "SentActivity":
def merge(cls, activity_params: SendableActivity, curr_activity: "SentActivity") -> "SentActivity":
merged_data = {**activity_params.model_dump(), **curr_activity.model_dump()}
return cls(**merged_data)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from microsoft_teams.common.experimental import experimental
from microsoft_teams.common.http import Client

from ...activities import ActivityParams, SentActivity
from ...activities import SendableActivity, SentActivity
from ...models import TeamsChannelAccount
from ..api_client_settings import ApiClientSettings
from ..base_client import BaseClient
Expand Down Expand Up @@ -38,7 +38,7 @@ def __init__(
super().__init__(http_client, api_client_settings)
self.service_url = service_url.rstrip("/")

async def create(self, conversation_id: str, activity: ActivityParams) -> SentActivity:
async def create(self, conversation_id: str, activity: SendableActivity) -> SentActivity:
"""
Create a new activity in a conversation.

Expand All @@ -61,7 +61,7 @@ async def create(self, conversation_id: str, activity: ActivityParams) -> SentAc
id = response.json().get("id", _PLACEHOLDER_ACTIVITY_ID)
return SentActivity(id=id, activity_params=activity)

async def update(self, conversation_id: str, activity_id: str, activity: ActivityParams) -> SentActivity:
async def update(self, conversation_id: str, activity_id: str, activity: SendableActivity) -> SentActivity:
"""
Update an existing activity in a conversation.

Expand All @@ -80,7 +80,7 @@ async def update(self, conversation_id: str, activity_id: str, activity: Activit
id = response.json()["id"]
return SentActivity(id=id, activity_params=activity)

async def reply(self, conversation_id: str, activity_id: str, activity: ActivityParams) -> SentActivity:
async def reply(self, conversation_id: str, activity_id: str, activity: SendableActivity) -> SentActivity:
"""
Reply to an activity in a conversation.

Expand Down Expand Up @@ -128,7 +128,7 @@ async def get_members(self, conversation_id: str, activity_id: str) -> List[Team
return [TeamsChannelAccount.model_validate(member) for member in response.json()]

@experimental("ExperimentalTeamsTargeted")
async def create_targeted(self, conversation_id: str, activity: ActivityParams) -> SentActivity:
async def create_targeted(self, conversation_id: str, activity: SendableActivity) -> SentActivity:
"""
Create a new targeted activity in a conversation.

Expand All @@ -153,7 +153,7 @@ async def create_targeted(self, conversation_id: str, activity: ActivityParams)
return SentActivity(id=id, activity_params=activity)

@experimental("ExperimentalTeamsTargeted")
async def update_targeted(self, conversation_id: str, activity_id: str, activity: ActivityParams) -> SentActivity:
async def update_targeted(self, conversation_id: str, activity_id: str, activity: SendableActivity) -> SentActivity:
"""
Update an existing targeted activity in a conversation.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from ...models import ConversationResource
from ..api_client_settings import ApiClientSettings
from ..base_client import BaseClient
from .activity import ActivityParams, ConversationActivityClient
from .activity import SendableActivity, ConversationActivityClient
from .member import ConversationMemberClient
from .params import CreateConversationParams

Expand All @@ -26,13 +26,13 @@ def __init__(self, client: "ConversationClient", conversation_id: str) -> None:
class ActivityOperations(ConversationOperations):
"""Operations for managing activities in a conversation."""

async def create(self, activity: ActivityParams):
async def create(self, activity: SendableActivity):
return await self._client.activities_client.create(self._conversation_id, activity)

async def update(self, activity_id: str, activity: ActivityParams):
async def update(self, activity_id: str, activity: SendableActivity):
return await self._client.activities_client.update(self._conversation_id, activity_id, activity)

async def reply(self, activity_id: str, activity: ActivityParams):
async def reply(self, activity_id: str, activity: SendableActivity):
return await self._client.activities_client.reply(self._conversation_id, activity_id, activity)

async def delete(self, activity_id: str):
Expand All @@ -41,11 +41,11 @@ async def delete(self, activity_id: str):
async def get_members(self, activity_id: str):
return await self._client.activities_client.get_members(self._conversation_id, activity_id)

async def create_targeted(self, activity: ActivityParams):
async def create_targeted(self, activity: SendableActivity):
"""Create a new targeted activity visible only to the specified recipient."""
return await self._client.activities_client.create_targeted(self._conversation_id, activity)

async def update_targeted(self, activity_id: str, activity: ActivityParams):
async def update_targeted(self, activity_id: str, activity: SendableActivity):
"""Update an existing targeted activity."""
return await self._client.activities_client.update_targeted(self._conversation_id, activity_id, activity)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import Any, Dict, List, Optional

from ...models import Account, CustomBaseModel
from .activity import ActivityParams
from .activity import SendableActivity


class CreateConversationParams(CustomBaseModel):
Expand All @@ -20,7 +20,7 @@ class CreateConversationParams(CustomBaseModel):
"""
The tenant ID for the conversation.
"""
activity: Optional[ActivityParams] = None
activity: Optional[SendableActivity] = None
"""
The initial activity to post in the conversation.
"""
Expand Down
8 changes: 4 additions & 4 deletions packages/api/tests/unit/test_sent_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
# pyright: basic

import pytest
from microsoft_teams.api.activities import ActivityParams, MessageActivityInput, SentActivity
from microsoft_teams.api.activities import SendableActivity, MessageActivityInput, SentActivity


@pytest.fixture
def mock_new_activity_params() -> ActivityParams:
"""Create a mock ActivityParams for testing."""
def mock_new_activity_params() -> SendableActivity:
"""Create a mock SendableActivity for testing."""
Comment on lines 11 to +13
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fixture name mock_new_activity_params still references the old ActivityParams type but now returns SendableActivity, which is confusing when reading failures/debugging. Rename the fixture (and its usages) to reflect SendableActivity (e.g., mock_new_sendable_activity).

Copilot uses AI. Check for mistakes.
return MessageActivityInput(
id="updated-id", type="message", text="updated message", locale="en-US", reply_to_id="activity-3"
)


@pytest.fixture
def mock_sent_activity(mock_new_activity_params: ActivityParams) -> SentActivity:
def mock_sent_activity(mock_new_activity_params: SendableActivity) -> SentActivity:
"""Create a mock SentActivity for testing."""
return SentActivity(
id="sent-1",
Expand Down
4 changes: 2 additions & 2 deletions packages/apps/src/microsoft_teams/apps/activity_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from typing import cast

from microsoft_teams.api import (
ActivityParams,
SendableActivity,
ApiClient,
ConversationReference,
MessageActivityInput,
Expand Down Expand Up @@ -36,7 +36,7 @@ def __init__(self, client: Client):
"""
self._client = client

async def send(self, activity: ActivityParams, ref: ConversationReference) -> SentActivity:
async def send(self, activity: SendableActivity, ref: ConversationReference) -> SentActivity:
"""
Send an activity to the Bot Framework.

Expand Down
4 changes: 2 additions & 2 deletions packages/apps/src/microsoft_teams/apps/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from microsoft_teams.api import (
Account,
ActivityBase,
ActivityParams,
SendableActivity,
ApiClient,
ClientCredentials,
ConversationAccount,
Expand Down Expand Up @@ -275,7 +275,7 @@ async def stop(self) -> None:
self._events.emit("error", ErrorEvent(error, context={"method": "stop"}))
raise

async def send(self, conversation_id: str, activity: str | ActivityParams | AdaptiveCard):
async def send(self, conversation_id: str, activity: str | SendableActivity | AdaptiveCard):
"""Send an activity proactively."""

if not self._initialized:
Expand Down
4 changes: 2 additions & 2 deletions packages/apps/src/microsoft_teams/apps/app_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from microsoft_teams.api import (
ActivityBase,
ActivityParams,
SendableActivity,
ActivityTypeAdapter,
ApiClient,
ApiClientSettings,
Expand Down Expand Up @@ -131,7 +131,7 @@ async def _build_context(
send = activityCtx.send

async def updated_send(
message: str | ActivityParams | AdaptiveCard,
message: str | SendableActivity | AdaptiveCard,
conversation_ref: Optional[ConversationReference] = None,
) -> SentActivity:
res = await send(message, conversation_ref)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from microsoft_teams.api import (
Account,
ActivityParams,
SendableActivity,
ApiClient,
ConversationAccount,
ConversationReference,
Expand Down Expand Up @@ -50,7 +50,7 @@ class FunctionContext(ClientContext, Generic[T]):
data: T
"""The function payload."""

async def send(self, activity: str | ActivityParams | AdaptiveCard) -> Optional[SentActivity]:
async def send(self, activity: str | SendableActivity | AdaptiveCard) -> Optional[SentActivity]:
"""
Send an activity to the current conversation.

Expand Down Expand Up @@ -81,7 +81,7 @@ async def send(self, activity: str | ActivityParams | AdaptiveCard) -> Optional[

return await self.activity_sender.send(activity, conversation_ref)

async def _resolve_conversation_id(self, activity: str | ActivityParams | AdaptiveCard) -> Optional[str]:
async def _resolve_conversation_id(self, activity: str | SendableActivity | AdaptiveCard) -> Optional[str]:
"""Resolve or create a conversation ID for the current user/context.

Args:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from microsoft_teams.api import (
ActivityBase,
ActivityParams,
SendableActivity,
ApiClient,
CardAction,
CardActionType,
Expand Down Expand Up @@ -71,7 +71,7 @@ class SignInOptions:
Optional[TokenPostResource],
Optional[str],
],
ActivityParams,
SendableActivity,
]
] = None

Expand Down Expand Up @@ -165,14 +165,14 @@ def app_graph(self) -> "GraphServiceClient":

async def send(
self,
message: str | ActivityParams | AdaptiveCard,
message: str | SendableActivity | AdaptiveCard,
conversation_ref: Optional[ConversationReference] = None,
) -> SentActivity:
"""
Send a message to the conversation.

Args:
message: The message to send, can be a string, ActivityParams, or AdaptiveCard
message: The message to send, can be a string, SendableActivity, or AdaptiveCard
conversation_ref: Optional conversation reference to override the current conversation reference
"""
if isinstance(message, str):
Expand All @@ -186,7 +186,7 @@ async def send(
res = await self._activity_sender.send(activity, ref)
return res

async def reply(self, input: str | ActivityParams) -> SentActivity:
async def reply(self, input: str | SendableActivity) -> SentActivity:
"""Send a reply to the activity."""
activity = MessageActivityInput(text=input) if isinstance(input, str) else input
if isinstance(activity, MessageActivityInput):
Expand Down
4 changes: 2 additions & 2 deletions packages/apps/tests/test_activity_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ async def test_reply_with_string(self) -> None:
assert "My reply" in (sent_activity.text or "")

@pytest.mark.asyncio
async def test_reply_with_activity_params(self) -> None:
"""reply() with an ActivityParams instance sets reply_to_id and delegates to send."""
async def test_reply_with_sendable_activity(self) -> None:
"""reply() with a SendableActivity instance sets reply_to_id and delegates to send."""
mock_activity = MagicMock()
mock_activity.type = "event"
mock_activity.id = "evt-id-999"
Expand Down
Loading