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 @@ -10,3 +10,4 @@ class RoleTypes(str, Enum):
skill = "skill"
agentic_identity = "agenticAppInstance"
agentic_user = "agenticUser"
connector_user = "connectoruser"
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
"""

from abc import ABC
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Unused import: ABC is imported on line 6 but never used, since _AuthorizationHandler is already an abstract base class.

Suggested change
from abc import ABC

Copilot uses AI. Check for mistakes.
from typing import Optional
import logging
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Unused import: logging is imported on line 8 but the logger is defined and never used in this module (only in subclasses).

Suggested change
import logging

Copilot uses AI. Check for mistakes.

from microsoft_agents.activity import TokenResponse

from ....turn_context import TurnContext
from ....storage import Storage
from ....authorization import Connections
from ...._oauth import _FlowStateTag
from ..auth_handler import AuthHandler
from .._sign_in_response import _SignInResponse

from ._authorization_handler import _AuthorizationHandler
Comment on lines +1 to +19
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Missing imports: ClaimsIdentity is referenced on line 71 but not imported. The file imports ABC but it's not used since _AuthorizationHandler is already an ABC.

Copilot uses AI. Check for mistakes.

class _ConnectorUserAuthorizationHandler(_AuthorizationHandler):
"""Authorization handler for connector user OAuth flow."""

# def get_obo_settings(self) -> dict:
# """Get On-Behalf-Of settings for the auth handler.

# :return: The OBO settings dictionary.
# :rtype: dict
# """
# return self._
Comment on lines +24 to +30
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

This comment appears to contain commented-out code.

Suggested change
# def get_obo_settings(self) -> dict:
# """Get On-Behalf-Of settings for the auth handler.
# :return: The OBO settings dictionary.
# :rtype: dict
# """
# return self._

Copilot uses AI. Check for mistakes.

async def _sign_in(
self,
context: TurnContext,
exchange_connection: Optional[str] = None,
exchange_scopes: Optional[list[str]] = None,
) -> _SignInResponse:
token_response = await self.get_refreshed_token(
context, exchange_connection, exchange_scopes
)
if token_response:
return _SignInResponse(
token_response=token_response, tag=_FlowStateTag.COMPLETE
)
return _SignInResponse(tag=_FlowStateTag.FAILURE)


async def get_refreshed_token(
self,
context: TurnContext,
exchange_connection: Optional[str] = None,
exchange_scopes: Optional[list[str]] = None,
) -> TokenResponse:

token_response = self.create_token_response(context)

Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Incomplete implementation: The get_refreshed_token method is missing a return statement. It should return the token_response created on line 55.

Suggested change
return token_response

Copilot uses AI. Check for mistakes.
async def _sign_out(self, context: TurnContext) -> None:
raise NotImplementedError

def create_token_response(self, context: TurnContext) -> TokenResponse:

if _ConnectorUserAuthorizationHandler._is_case_sensitive_claims_identity(
context.turn_state.get("claims_identity")
Comment on lines +61 to +63
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Undefined variable: identity is used on line 65 but is not defined in the scope of the create_token_response method.

Suggested change
if _ConnectorUserAuthorizationHandler._is_case_sensitive_claims_identity(
context.turn_state.get("claims_identity")
identity = context.turn_state.get("claims_identity")
if _ConnectorUserAuthorizationHandler._is_case_sensitive_claims_identity(
identity

Copilot uses AI. Check for mistakes.
):
token_response = TokenResponse(token=identity.security_token.unsafe_to_str())

try:
jwt_token =
Comment on lines +60 to +68
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Incomplete implementation: The create_token_response method is incomplete. Lines 67-68 appear to be unfinished code with an incomplete variable assignment (jwt_token = ). This code will not compile.

Copilot uses AI. Check for mistakes.

@staticmethod
def _is_case_sensitive_claims_identity(identity: ClaimsIdentity) -> bool:
return False
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .connector_client import ConnectorClient
from .mcs_connector_client import MCSConnectorClient
from .user_token_client import UserTokenClient

__all__ = ["ConnectorClient", "UserTokenClient"]
__all__ = ["ConnectorClient", "MCSConnectorClient", "UserTokenClient"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

"""Connector Client for Microsoft Agents."""

import logging
from typing import Any, Optional
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Import of 'Any' is not used.

Suggested change
from typing import Any, Optional
from typing import Optional

Copilot uses AI. Check for mistakes.
from aiohttp import ClientSession
from io import BytesIO
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Unused import: BytesIO is imported on line 9 but never used in the code.

Suggested change
from io import BytesIO

Copilot uses AI. Check for mistakes.

from microsoft_agents.activity import (
Activity,
ChannelAccount,
ConversationParameters,
ConversationResourceResponse,
ResourceResponse,
ConversationsResult,
PagedMembersResult,
)
from microsoft_agents.hosting.core.connector import ConnectorClientBase
from ..attachments_base import AttachmentsBase
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Import of 'AttachmentsBase' is not used.

Suggested change
from ..attachments_base import AttachmentsBase

Copilot uses AI. Check for mistakes.
from ..conversations_base import ConversationsBase
from .connector_client import AttachmentsOperations
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Import of 'AttachmentsOperations' is not used.

Suggested change
from .connector_client import AttachmentsOperations

Copilot uses AI. Check for mistakes.
from ..get_product_info import get_product_info
Comment on lines +11 to +24
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Missing imports: Transcript and AttachmentData are used in method signatures (lines 56 and 62) but are not imported.

Copilot uses AI. Check for mistakes.


logger = logging.getLogger(__name__)

class MCSConversationsOperations(ConversationsBase):
"""Operations for managing conversations in MCS."""

def __init__(self, client: ClientSession):
self.client = client

async def create_conversation(self, body: ConversationParameters) -> ConversationResourceResponse:
raise NotImplementedError()

async def delete_activity(self, conversation_id: str, activity_id: str) -> None:
raise NotImplementedError()

async def delete_conversation_member(self, conversation_id: str, member_id: str) -> None:
raise NotImplementedError()

async def get_activity_members(self, conversation_id: str, activity_id: str) -> list[ChannelAccount]:
raise NotImplementedError()

async def get_conversation_member(self, conversation_id: str, member_id: str) -> ChannelAccount:
raise NotImplementedError()

async def get_conversation_members(self, conversation_id: str) -> list[ChannelAccount]:
raise NotImplementedError()

async def get_conversations(self, continuation_token: Optional[str] = None) -> ConversationsResult:
raise NotImplementedError()

async def send_conversation_history(self, conversation_id: str, transcript: Transcript) -> ResourceResponse:
raise NotImplementedError()

async def update_activity(self, conversation_id: str, activity_id: str, activity: Activity) -> ResourceResponse:
raise NotImplementedError()

async def upload_attachment(self, conversation_id: str, attachment_upload: AttachmentData) -> ResourceResponse:
raise NotImplementedError()

async def get_conversation_paged_members(
self,
conversation_id: str,
page_size: Optional[int] = None,
continuation_token: Optional[str] = None,
) -> PagedMembersResult:
raise NotImplementedError()

async def send_to_conversation(self, conversation_id: str, body: Activity) -> ResourceResponse:
if not conversation_id:
raise ValueError("conversation_id cannot be None or empty.")

async with self.client.post(
url="",
json=body.model_dump(by_alias=True, exclude_unset=True, mode="json"),
) as response:
if response.status >= 300:
logger.error(
"Error sending to conversation: %s",
response.status,
stack_info=True,
)
response.raise_for_status()

data = await response.json()
return ResourceResponse.model_validate(data)

async def reply_to_activity(self, conversation_id: str, body: Activity) -> ResourceResponse:
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

This method requires 3 positional arguments, whereas overridden ConversationsBase.reply_to_activity requires 4.

Suggested change
async def reply_to_activity(self, conversation_id: str, body: Activity) -> ResourceResponse:
async def reply_to_activity(self, conversation_id: str, activity_id: str, body: Activity) -> ResourceResponse:
# The activity_id argument is accepted for signature compatibility, but not used in this implementation.

Copilot uses AI. Check for mistakes.
return await self.send_to_conversation(conversation_id, body)

# Implement conversation-related methods as needed

class MCSConnectorClient(ConnectorClientBase):

def __init__(self, endpoint: str, *, session: ClientSession = None):
"""
Initialize a new instance of ConnectorClient.

:param session: The aiohttp ClientSession to use for HTTP requests.
"""
if not endpoint.endswith("/"):
endpoint += "/"

# Configure headers with JSON acceptance
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"User-Agent": get_product_info(),
}
# Create session with the base URL
session = session or ClientSession(
base_url=endpoint,
headers=headers,
)
logger.debug(
"ConnectorClient initialized with endpoint: %s and headers: %s",
endpoint,
headers,
)

self.client = session
self._attachments = AttachmentOperations(
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Line 126 references AttachmentOperations but the import on line 23 is AttachmentsOperations (plural). This will cause a NameError at runtime.

Suggested change
self._attachments = AttachmentOperations(
self._attachments = AttachmentsOperations(

Copilot uses AI. Check for mistakes.
self.client
) # Will implement if needed
self._conversations = MCSConversationsOperations(
self.client
) # Will implement if needed
Comment on lines +97 to +131
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Missing required properties: The MCSConnectorClient class inherits from ConnectorClientBase which requires implementing base_uri, attachments, and conversations as properties. These should be exposed as @property methods instead of just instance variables.

Copilot uses AI. Check for mistakes.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ async def create_connector_client(
"RestChannelServiceClientFactory.create_connector_client: audience can't be None or Empty"
)

if context.activity.recipient and context.activity.recipient.role == RoleTypes.connector_user:
return MCSConnectorClient(turn_context.activity.service_url)
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Variable name inconsistency: Line 104 uses context but line 105 uses turn_context. These should refer to the same variable. Based on the function parameter name context on line 101, line 105 should use context.activity.service_url instead of turn_context.activity.service_url.

Suggested change
return MCSConnectorClient(turn_context.activity.service_url)
return MCSConnectorClient(context.activity.service_url)

Copilot uses AI. Check for mistakes.
Comment on lines +104 to +105
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Missing import: MCSConnectorClient is used on line 105 but is not imported. The import statement needs to be updated to include MCSConnectorClient.

Copilot uses AI. Check for mistakes.
if context.activity.is_agentic_request():
token = await self._get_agentic_token(context, service_url)
else:
Expand Down
Loading