Python: Introducing UserInputRequest and Response types and HostedMcpTool (#405)

* initial work on User Approval (and hosted mcp to validate)

* small update to the comments in the sample

* enable local MCP tools in chatClient get methods

* working streaming and improved setup

* fix for pyright

* updated create_approval -> create_response method

* added tests

* updated HostedMcpTool and addressed feedback

* update type name

* naming updates

* small docstring update

* mypy fix

* fixes and updates

* fixes for responses

* fix int tests

* removed broken tests

* updated test running

* removed specific content check on websearch

* increased timeout

* split slow foundry test

* don't parallel run samples

* add dist load to unit tests

---------

Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
This commit is contained in:
Eduard van Valkenburg
2025-09-10 15:37:34 +02:00
committed by GitHub
Unverified
parent 947f2bf642
commit 6aa746d891
21 changed files with 1186 additions and 447 deletions
@@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Any, Generic, Literal, Protocol, TypeVar, runt
from pydantic import BaseModel
from ._logging import get_logger
from ._mcp import MCPTool
from ._pydantic import AFBaseModel
from ._threads import ChatMessageStore
from ._tools import AIFunction, ToolProtocol
@@ -391,6 +392,25 @@ class BaseChatClient(AFBaseModel, ABC):
return_messages.append(msg)
return return_messages
@staticmethod
def _normalize_tools(
tools: ToolProtocol
| MutableMapping[str, Any]
| Callable[..., Any]
| list[ToolProtocol | MutableMapping[str, Any] | Callable[..., Any]]
| None = None,
) -> list[ToolProtocol | dict[str, Any] | Callable[..., Any]]:
"""Normalize the tools input to a list of tools."""
final_tools: list[ToolProtocol | dict[str, Any] | Callable[..., Any]] = []
if not tools:
return final_tools
for tool in tools if isinstance(tools, list) else [tools]: # type: ignore[reportUnknownType]
if isinstance(tool, MCPTool):
final_tools.extend(tool.functions) # type: ignore
continue
final_tools.append(tool) # type: ignore
return final_tools
# region Internal methods to be implemented by the derived classes
@abstractmethod
@@ -513,7 +533,7 @@ class BaseChatClient(AFBaseModel, ABC):
temperature=temperature,
top_p=top_p,
tool_choice=tool_choice,
tools=tools, # type: ignore
tools=self._normalize_tools(tools), # type: ignore
user=user,
additional_properties=additional_properties or {},
)
@@ -592,7 +612,7 @@ class BaseChatClient(AFBaseModel, ABC):
temperature=temperature,
top_p=top_p,
tool_choice=tool_choice,
tools=tools, # type: ignore
tools=self._normalize_tools(tools), # type: ignore
user=user,
additional_properties=additional_properties or {},
**kwargs,