mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Fix: Parse oauth_consent_request events in Azure AI client (#4197)
* Fix: Parse oauth_consent_request events in Azure AI client (#3950) When Azure AI Agent Service returns an oauth_consent_request output item for OAuth-protected MCP tools, the base OpenAI responses parser drops it (hits case _ default branch). This causes agent runs to complete silently with zero content. Changes: - Add oauth_consent_request ContentType and Content.from_oauth_consent_request() factory with consent_link field and user_input_request=True - Override _parse_response_from_openai and _parse_chunk_from_openai in RawAzureAIClient to intercept Azure-specific oauth_consent_request items - Add _emit_oauth_consent helper in AG-UI to emit CustomEvent for frontends - Add tests proving base parser drops the event and Azure AI override catches it Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * addressed comment * addressed comments * addressed comments --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
7135ed13eb
commit
2b3c401848
@@ -345,6 +345,7 @@ ContentType = Literal[
|
||||
"shell_command_output",
|
||||
"function_approval_request",
|
||||
"function_approval_response",
|
||||
"oauth_consent_request",
|
||||
]
|
||||
|
||||
|
||||
@@ -498,6 +499,8 @@ class Content:
|
||||
function_call: Content | None = None,
|
||||
user_input_request: bool | None = None,
|
||||
approved: bool | None = None,
|
||||
# OAuth consent fields
|
||||
consent_link: str | None = None,
|
||||
# Common fields
|
||||
annotations: Sequence[Annotation] | None = None,
|
||||
additional_properties: MutableMapping[str, Any] | None = None,
|
||||
@@ -546,6 +549,7 @@ class Content:
|
||||
self.function_call = function_call
|
||||
self.user_input_request = user_input_request
|
||||
self.approved = approved
|
||||
self.consent_link = consent_link
|
||||
|
||||
@classmethod
|
||||
def from_text(
|
||||
@@ -1122,6 +1126,37 @@ class Content:
|
||||
raw_representation=raw_representation,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_oauth_consent_request(
|
||||
cls: type[ContentT],
|
||||
consent_link: str,
|
||||
*,
|
||||
annotations: Sequence[Annotation] | None = None,
|
||||
additional_properties: MutableMapping[str, Any] | None = None,
|
||||
raw_representation: Any = None,
|
||||
) -> ContentT:
|
||||
"""Create OAuth consent request content.
|
||||
|
||||
Args:
|
||||
consent_link: The URL the user must visit to complete OAuth consent.
|
||||
|
||||
Keyword Args:
|
||||
annotations: Optional annotations.
|
||||
additional_properties: Optional additional properties.
|
||||
raw_representation: Optional raw representation from the provider.
|
||||
|
||||
Returns:
|
||||
A new Content instance with type ``oauth_consent_request``.
|
||||
"""
|
||||
return cls(
|
||||
"oauth_consent_request",
|
||||
consent_link=consent_link,
|
||||
user_input_request=True,
|
||||
annotations=annotations,
|
||||
additional_properties=additional_properties,
|
||||
raw_representation=raw_representation,
|
||||
)
|
||||
|
||||
def to_function_approval_response(
|
||||
self,
|
||||
approved: bool,
|
||||
@@ -1176,6 +1211,7 @@ class Content:
|
||||
"user_input_request",
|
||||
"approved",
|
||||
"id",
|
||||
"consent_link",
|
||||
"additional_properties",
|
||||
)
|
||||
|
||||
|
||||
@@ -3424,3 +3424,30 @@ class TestResponseStreamEdgeCases:
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
# region OAuth Consent Content
|
||||
|
||||
|
||||
def test_oauth_consent_request_creation():
|
||||
"""Test Content.from_oauth_consent_request creates the correct content."""
|
||||
content = Content.from_oauth_consent_request(
|
||||
consent_link="https://login.microsoftonline.com/common/oauth2/authorize?client_id=abc",
|
||||
)
|
||||
assert content.type == "oauth_consent_request"
|
||||
assert content.consent_link == "https://login.microsoftonline.com/common/oauth2/authorize?client_id=abc"
|
||||
assert content.user_input_request is True
|
||||
|
||||
|
||||
def test_oauth_consent_request_serialization_roundtrip():
|
||||
"""Test that oauth_consent_request content serializes and includes consent_link."""
|
||||
content = Content.from_oauth_consent_request(
|
||||
consent_link="https://login.microsoftonline.com/consent",
|
||||
)
|
||||
d = content.to_dict()
|
||||
assert d["type"] == "oauth_consent_request"
|
||||
assert d["consent_link"] == "https://login.microsoftonline.com/consent"
|
||||
assert d["user_input_request"] is True
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
Reference in New Issue
Block a user