Skip to content
Merged
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 @@ -14,6 +14,8 @@
model_serializer,
)

from microsoft_agents.activity.errors import activity_errors

from .channel_id import ChannelId

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -42,10 +44,7 @@ def channel_id(self, value: Any):
elif isinstance(value, str):
self._channel_id = ChannelId(value)
else:
raise ValueError(
f"Invalid type for channel_id: {type(value)}. "
"Expected ChannelId or str."
)
raise ValueError(activity_errors.InvalidChannelIdType.format(type(value)))

def _set_validated_channel_id(self, data: Any) -> None:
"""Sets the channel_id after validating it as a ChannelId model."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from .channel_id import ChannelId
from ._model_utils import pick_model, SkipNone
from ._type_aliases import NonEmptyString
from microsoft_agents.activity.errors import activity_errors

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -218,9 +219,7 @@ def _validate_channel_id(
activity.channel_id.sub_channel
and activity.channel_id.sub_channel != product_info.id
):
raise Exception(
"Conflict between channel_id.sub_channel and productInfo entity"
)
raise Exception(str(activity_errors.ChannelIdProductInfoConflict))
activity.channel_id = ChannelId(
channel=activity.channel_id.channel,
sub_channel=product_info.id,
Expand Down Expand Up @@ -256,9 +255,7 @@ def _serialize_sub_channel_data(
# self.channel_id is the source of truth for serialization
if self.channel_id and self.channel_id.sub_channel:
if product_info and product_info.get("id") != self.channel_id.sub_channel:
raise Exception(
"Conflict between channel_id.sub_channel and productInfo entity"
)
raise Exception(str(activity_errors.ChannelIdProductInfoConflict))
elif not product_info:
if not serialized.get("entities"):
serialized["entities"] = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from pydantic_core import CoreSchema, core_schema
from pydantic import GetCoreSchemaHandler

from microsoft_agents.activity.errors import activity_errors


class ChannelId(str):
"""A ChannelId represents a channel and optional sub-channel in the format 'channel:sub_channel'."""
Expand Down Expand Up @@ -52,14 +54,12 @@ def __new__(
"""
if isinstance(value, str):
if channel or sub_channel:
raise ValueError(
"If value is provided, channel and sub_channel must be None"
)
raise ValueError(str(activity_errors.ChannelIdValueConflict))

value = value.strip()
if value:
return str.__new__(cls, value)
raise TypeError("value must be a non empty string if provided")
raise TypeError(str(activity_errors.ChannelIdValueMustBeNonEmpty))
else:
if (
not isinstance(channel, str)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

"""
Error resources for Microsoft Agents Activity package.
"""

from microsoft_agents.hosting.core.errors import ErrorMessage

from .error_resources import ActivityErrorResources

# Singleton instance
activity_errors = ActivityErrorResources()

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

"""
Activity error resources for Microsoft Agents SDK.

Error codes are in the range -64000 to -64999.
"""

from microsoft_agents.hosting.core.errors import ErrorMessage


class ActivityErrorResources:
"""
Error messages for activity operations.

Error codes are organized in the range -64000 to -64999.
"""

InvalidChannelIdType = ErrorMessage(
"Invalid type for channel_id: {0}. Expected ChannelId or str.",
-64000,
"activity-schema",
)

ChannelIdProductInfoConflict = ErrorMessage(
"Conflict between channel_id.sub_channel and productInfo entity",
-64001,
"activity-schema",
)

ChannelIdValueConflict = ErrorMessage(
"If value is provided, channel and sub_channel must be None",
-64002,
"activity-schema",
)

ChannelIdValueMustBeNonEmpty = ErrorMessage(
"value must be a non empty string if provided",
-64003,
"activity-schema",
)

InvalidFromPropertyType = ErrorMessage(
"Invalid type for from_property: {0}. Expected ChannelAccount or dict.",
-64004,
"activity-schema",
)

InvalidRecipientType = ErrorMessage(
"Invalid type for recipient: {0}. Expected ChannelAccount or dict.",
-64005,
"activity-schema",
)

def __init__(self):
"""Initialize ActivityErrorResources."""
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

"""
Error resources for Microsoft Agents Authentication MSAL package.
"""

from microsoft_agents.hosting.core.errors import ErrorMessage

from .error_resources import AuthenticationErrorResources

# Singleton instance
authentication_errors = AuthenticationErrorResources()

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

"""
Authentication error resources for Microsoft Agents SDK.

Error codes are in the range -60000 to -60999.
"""

from microsoft_agents.hosting.core.errors import ErrorMessage


class AuthenticationErrorResources:
"""
Error messages for authentication operations.

Error codes are organized in the range -60000 to -60999.
"""

FailedToAcquireToken = ErrorMessage(
"Failed to acquire token. {0}",
-60012,
"agentic-identity-with-the-m365-agents-sdk",
)

InvalidInstanceUrl = ErrorMessage(
"Invalid instance URL",
-60013,
"agentic-identity-with-the-m365-agents-sdk",
)

OnBehalfOfFlowNotSupportedManagedIdentity = ErrorMessage(
"On-behalf-of flow is not supported with Managed Identity authentication.",
-60014,
"agentic-identity-with-the-m365-agents-sdk",
)

OnBehalfOfFlowNotSupportedAuthType = ErrorMessage(
"On-behalf-of flow is not supported with the current authentication type: {0}",
-60015,
"agentic-identity-with-the-m365-agents-sdk",
)

AuthenticationTypeNotSupported = ErrorMessage(
"Authentication type not supported",
-60016,
"agentic-identity-with-the-m365-agents-sdk",
)

AgentApplicationInstanceIdRequired = ErrorMessage(
"Agent application instance Id must be provided.",
-60017,
"agentic-identity-with-the-m365-agents-sdk",
)

FailedToAcquireAgenticInstanceToken = ErrorMessage(
"Failed to acquire agentic instance token or agent token for agent_app_instance_id {0}",
-60018,
"agentic-identity-with-the-m365-agents-sdk",
)

AgentApplicationInstanceIdAndUserIdRequired = ErrorMessage(
"Agent application instance Id and agentic user Id must be provided.",
-60019,
"agentic-identity-with-the-m365-agents-sdk",
)

FailedToAcquireInstanceOrAgentToken = ErrorMessage(
"Failed to acquire instance token or agent token for agent_app_instance_id {0} and agentic_user_id {1}",
-60020,
"agentic-identity-with-the-m365-agents-sdk",
)

def __init__(self):
"""Initialize AuthenticationErrorResources."""
pass
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
AccessTokenProviderBase,
AgentAuthConfiguration,
)
from microsoft_agents.authentication.msal.errors import authentication_errors

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -65,7 +66,7 @@ async def get_access_token(
)
valid_uri, instance_uri = self._uri_validator(resource_url)
if not valid_uri:
raise ValueError("Invalid instance URL")
raise ValueError(str(authentication_errors.InvalidInstanceUrl))

local_scopes = self._resolve_scopes_list(instance_uri, scopes)
self._create_client_application()
Expand All @@ -86,7 +87,11 @@ async def get_access_token(
res = auth_result_payload.get("access_token") if auth_result_payload else None
if not res:
logger.error("Failed to acquire token for resource %s", auth_result_payload)
raise ValueError(f"Failed to acquire token. {str(auth_result_payload)}")
raise ValueError(
authentication_errors.FailedToAcquireToken.format(
str(auth_result_payload)
)
)

return res

Expand All @@ -106,7 +111,7 @@ async def acquire_token_on_behalf_of(
"Attempted on-behalf-of flow with Managed Identity authentication."
)
raise NotImplementedError(
"On-behalf-of flow is not supported with Managed Identity authentication."
str(authentication_errors.OnBehalfOfFlowNotSupportedManagedIdentity)
)
elif isinstance(self._msal_auth_client, ConfidentialClientApplication):
# TODO: Handling token error / acquisition failed
Expand All @@ -123,15 +128,19 @@ async def acquire_token_on_behalf_of(
logger.error(
f"Failed to acquire token on behalf of user: {user_assertion}"
)
raise ValueError(f"Failed to acquire token. {str(token)}")
raise ValueError(
authentication_errors.FailedToAcquireToken.format(str(token))
)

return token["access_token"]

logger.error(
f"On-behalf-of flow is not supported with the current authentication type: {self._msal_auth_client.__class__.__name__}"
)
raise NotImplementedError(
f"On-behalf-of flow is not supported with the current authentication type: {self._msal_auth_client.__class__.__name__}"
authentication_errors.OnBehalfOfFlowNotSupportedAuthType.format(
self._msal_auth_client.__class__.__name__
)
)

def _create_client_application(self) -> None:
Expand Down Expand Up @@ -187,7 +196,9 @@ def _create_client_application(self) -> None:
logger.error(
f"Unsupported authentication type: {self._msal_configuration.AUTH_TYPE}"
)
raise NotImplementedError("Authentication type not supported")
raise NotImplementedError(
str(authentication_errors.AuthenticationTypeNotSupported)
)

self._msal_auth_client = ConfidentialClientApplication(
client_id=self._msal_configuration.CLIENT_ID,
Expand Down Expand Up @@ -233,7 +244,9 @@ async def get_agentic_application_token(
"""

if not agent_app_instance_id:
raise ValueError("Agent application instance Id must be provided.")
raise ValueError(
str(authentication_errors.AgentApplicationInstanceIdRequired)
)

logger.info(
"Attempting to get agentic application token from agent_app_instance_id %s",
Expand Down Expand Up @@ -267,7 +280,9 @@ async def get_agentic_instance_token(
"""

if not agent_app_instance_id:
raise ValueError("Agent application instance Id must be provided.")
raise ValueError(
str(authentication_errors.AgentApplicationInstanceIdRequired)
)

logger.info(
"Attempting to get agentic instance token from agent_app_instance_id %s",
Expand All @@ -283,7 +298,9 @@ async def get_agentic_instance_token(
agent_app_instance_id,
)
raise Exception(
f"Failed to acquire agentic instance token or agent token for agent_app_instance_id {agent_app_instance_id}"
authentication_errors.FailedToAcquireAgenticInstanceToken.format(
agent_app_instance_id
)
)

authority = (
Expand All @@ -306,7 +323,9 @@ async def get_agentic_instance_token(
agent_app_instance_id,
)
raise Exception(
f"Failed to acquire agentic instance token or agent token for agent_app_instance_id {agent_app_instance_id}"
authentication_errors.FailedToAcquireAgenticInstanceToken.format(
agent_app_instance_id
)
)

# future scenario where we don't know the blueprint id upfront
Expand All @@ -316,7 +335,11 @@ async def get_agentic_instance_token(
logger.error(
"Failed to acquire agentic instance token, %s", agentic_instance_token
)
raise ValueError(f"Failed to acquire token. {str(agentic_instance_token)}")
raise ValueError(
authentication_errors.FailedToAcquireToken.format(
str(agentic_instance_token)
)
)

logger.debug(
"Agentic blueprint id: %s",
Expand Down Expand Up @@ -345,7 +368,7 @@ async def get_agentic_user_token(
"""
if not agent_app_instance_id or not agentic_user_id:
raise ValueError(
"Agent application instance Id and agentic user Id must be provided."
str(authentication_errors.AgentApplicationInstanceIdAndUserIdRequired)
)

logger.info(
Expand All @@ -364,7 +387,9 @@ async def get_agentic_user_token(
agentic_user_id,
)
raise Exception(
f"Failed to acquire instance token or agent token for agent_app_instance_id {agent_app_instance_id} and agentic_user_id {agentic_user_id}"
authentication_errors.FailedToAcquireInstanceOrAgentToken.format(
agent_app_instance_id, agentic_user_id
)
)

authority = (
Expand Down
Loading