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 @@ -3,7 +3,7 @@

"""Channel service route definitions (framework-agnostic logic)."""

from typing import Type
from typing import Type, TypeVar

from microsoft_agents.activity import (
AgentsModel,
Expand All @@ -16,6 +16,8 @@

from ._http_request_protocol import HttpRequestProtocol

AgentsModelT = TypeVar("AgentsModelT", bound=AgentsModel)


class ChannelServiceRoutes:
"""Defines the Channel Service API routes and their handlers.
Expand All @@ -36,8 +38,8 @@ def __init__(self, handler: ChannelApiHandlerProtocol, base_url: str = ""):

@staticmethod
async def deserialize_from_body(
request: HttpRequestProtocol, target_model: Type[AgentsModel]
) -> AgentsModel:
request: HttpRequestProtocol, target_model: Type[AgentsModelT]
) -> AgentsModelT:
"""Deserialize request body to target model."""
content_type = request.headers.get("Content-Type", "")
if "application/json" not in content_type:
Expand All @@ -47,7 +49,9 @@ async def deserialize_from_body(
return target_model.model_validate(body)
Comment thread
rodrigobr-msft marked this conversation as resolved.
Comment on lines 39 to 49

@staticmethod
def serialize_model(model_or_list: AgentsModel | list[AgentsModel]) -> dict:
def serialize_model(
model_or_list: AgentsModelT | list[AgentsModelT],
) -> dict | list[dict]:
"""Serialize model or list of models to JSON-compatible dict."""
if isinstance(model_or_list, AgentsModel):
return model_or_list.model_dump(
Expand All @@ -60,7 +64,9 @@ def serialize_model(model_or_list: AgentsModel | list[AgentsModel]) -> dict:
]

# Route handler methods
async def send_to_conversation(self, request: HttpRequestProtocol) -> dict:
async def send_to_conversation(
self, request: HttpRequestProtocol
) -> dict | list[dict]:
"""Handle POST /v3/conversations/{conversation_id}/activities."""
activity = await self.deserialize_from_body(request, Activity)
conversation_id = request.get_path_param("conversation_id")
Expand All @@ -71,7 +77,9 @@ async def send_to_conversation(self, request: HttpRequestProtocol) -> dict:
)
return self.serialize_model(result)

async def reply_to_activity(self, request: HttpRequestProtocol) -> dict:
async def reply_to_activity(
self, request: HttpRequestProtocol
) -> dict | list[dict]:
"""Handle POST /v3/conversations/{conversation_id}/activities/{activity_id}."""
activity = await self.deserialize_from_body(request, Activity)
conversation_id = request.get_path_param("conversation_id")
Expand All @@ -84,7 +92,7 @@ async def reply_to_activity(self, request: HttpRequestProtocol) -> dict:
)
return self.serialize_model(result)

async def update_activity(self, request: HttpRequestProtocol) -> dict:
async def update_activity(self, request: HttpRequestProtocol) -> dict | list[dict]:
"""Handle PUT /v3/conversations/{conversation_id}/activities/{activity_id}."""
activity = await self.deserialize_from_body(request, Activity)
conversation_id = request.get_path_param("conversation_id")
Expand All @@ -107,7 +115,9 @@ async def delete_activity(self, request: HttpRequestProtocol) -> None:
activity_id,
)

async def get_activity_members(self, request: HttpRequestProtocol) -> dict:
async def get_activity_members(
self, request: HttpRequestProtocol
) -> dict | list[dict]:
"""Handle GET /v3/conversations/{conversation_id}/activities/{activity_id}/members."""
conversation_id = request.get_path_param("conversation_id")
activity_id = request.get_path_param("activity_id")
Expand All @@ -118,7 +128,9 @@ async def get_activity_members(self, request: HttpRequestProtocol) -> dict:
)
return self.serialize_model(result)

async def create_conversation(self, request: HttpRequestProtocol) -> dict:
async def create_conversation(
self, request: HttpRequestProtocol
) -> dict | list[dict]:
"""Handle POST /."""
conversation_parameters = await self.deserialize_from_body(
request, ConversationParameters
Expand All @@ -128,15 +140,19 @@ async def create_conversation(self, request: HttpRequestProtocol) -> dict:
)
return self.serialize_model(result)

async def get_conversations(self, request: HttpRequestProtocol) -> dict:
async def get_conversations(
self, request: HttpRequestProtocol
) -> dict | list[dict]:
"""Handle GET /."""
# TODO: continuation token? conversation_id?
result = await self.handler.on_get_conversations(
request.get_claims_identity(), None
)
return self.serialize_model(result)
Comment thread
rodrigobr-msft marked this conversation as resolved.

async def get_conversation_members(self, request: HttpRequestProtocol) -> dict:
async def get_conversation_members(
self, request: HttpRequestProtocol
) -> dict | list[dict]:
"""Handle GET /v3/conversations/{conversation_id}/members."""
conversation_id = request.get_path_param("conversation_id")
result = await self.handler.on_get_conversation_members(
Expand All @@ -145,7 +161,9 @@ async def get_conversation_members(self, request: HttpRequestProtocol) -> dict:
)
return self.serialize_model(result)

async def get_conversation_member(self, request: HttpRequestProtocol) -> dict:
async def get_conversation_member(
self, request: HttpRequestProtocol
) -> dict | list[dict]:
"""Handle GET /v3/conversations/{conversation_id}/members/{member_id}."""
conversation_id = request.get_path_param("conversation_id")
member_id = request.get_path_param("member_id")
Expand All @@ -158,7 +176,7 @@ async def get_conversation_member(self, request: HttpRequestProtocol) -> dict:

async def get_conversation_paged_members(
self, request: HttpRequestProtocol
) -> dict:
) -> dict | list[dict]:
"""Handle GET /v3/conversations/{conversation_id}/pagedmembers."""
conversation_id = request.get_path_param("conversation_id")
# TODO: continuation token? page size?
Expand All @@ -168,18 +186,19 @@ async def get_conversation_paged_members(
)
return self.serialize_model(result)

async def delete_conversation_member(self, request: HttpRequestProtocol) -> dict:
async def delete_conversation_member(self, request: HttpRequestProtocol) -> None:
"""Handle DELETE /v3/conversations/{conversation_id}/members/{member_id}."""
conversation_id = request.get_path_param("conversation_id")
member_id = request.get_path_param("member_id")
result = await self.handler.on_delete_conversation_member(
await self.handler.on_delete_conversation_member(
request.get_claims_identity(),
conversation_id,
member_id,
)
Comment on lines +189 to 197
return self.serialize_model(result)

async def send_conversation_history(self, request: HttpRequestProtocol) -> dict:
async def send_conversation_history(
self, request: HttpRequestProtocol
) -> dict | list[dict]:
"""Handle POST /v3/conversations/{conversation_id}/activities/history."""
conversation_id = request.get_path_param("conversation_id")
transcript = await self.deserialize_from_body(request, Transcript)
Expand All @@ -190,7 +209,9 @@ async def send_conversation_history(self, request: HttpRequestProtocol) -> dict:
)
return self.serialize_model(result)

async def upload_attachment(self, request: HttpRequestProtocol) -> dict:
async def upload_attachment(
self, request: HttpRequestProtocol
) -> dict | list[dict]:
"""Handle POST /v3/conversations/{conversation_id}/attachments."""
conversation_id = request.get_path_param("conversation_id")
attachment_data = await self.deserialize_from_body(request, AttachmentData)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def ok(body: Any = None) -> HttpResponse:
@staticmethod
def accepted() -> HttpResponse:
"""Create 202 Accepted response."""
return HttpResponse(status_code=202)
return HttpResponse(status_code=202, content_type=None)

@staticmethod
def json(body: Any, status_code: int = 200) -> HttpResponse:
Expand Down
Loading