mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Simplify Python hosting core (#6492)
Remove linking, multicast, durable delivery, and host push machinery from the v1 hosting core. Keep those scenarios in a proposed follow-up ADR and update channel packages, samples, docs, tests, and workspace metadata around the smaller host/channel contract. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
co-authored by
Copilot
parent
e5a6e35843
commit
36ce0950e4
@@ -11,12 +11,11 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import contextlib
|
||||
from collections.abc import Mapping
|
||||
from collections.abc import Awaitable, Mapping
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
from agent_framework import AgentResponse, Content, Message
|
||||
from agent_framework_hosting import (
|
||||
AgentFrameworkHost,
|
||||
ChannelCommand,
|
||||
@@ -119,10 +118,6 @@ class _FakeAgent:
|
||||
return _coro()
|
||||
|
||||
|
||||
def _run_result(text: str) -> HostedRunResult[AgentResponse]:
|
||||
return HostedRunResult(AgentResponse(messages=[Message(role="assistant", contents=[Content.from_text(text=text)])]))
|
||||
|
||||
|
||||
def _make_telegram(
|
||||
stream_default: bool = False, *, path: str = "/telegram/webhook"
|
||||
) -> tuple[TelegramChannel, _FakeAgent]:
|
||||
@@ -186,10 +181,10 @@ class TestTelegramWebhook:
|
||||
assert not agent.runs
|
||||
|
||||
async def test_response_hook_can_rewrite_originating_reply(self) -> None:
|
||||
contexts: list[Any] = []
|
||||
seen_kwargs: list[dict[str, Any]] = []
|
||||
|
||||
def hook(result: HostedRunResult, **kwargs: Any) -> HostedRunResult:
|
||||
contexts.append(kwargs["context"])
|
||||
seen_kwargs.append(dict(kwargs))
|
||||
return HostedRunResult(_FakeAgentResponse(text=result.result.text.upper()), session=result.session)
|
||||
|
||||
ch, agent = _make_telegram()
|
||||
@@ -198,11 +193,22 @@ class TestTelegramWebhook:
|
||||
class _Ctx:
|
||||
target: Any = agent
|
||||
|
||||
async def run(self, _request: ChannelRequest) -> HostedRunResult:
|
||||
return HostedRunResult(_FakeAgentResponse(text="hi"))
|
||||
|
||||
async def deliver_response(self, _request: ChannelRequest, _payload: HostedRunResult) -> bool:
|
||||
return True
|
||||
async def run(
|
||||
self,
|
||||
_request: ChannelRequest,
|
||||
*,
|
||||
run_hook: Any | None = None,
|
||||
protocol_request: Any | None = None,
|
||||
response_hook: Any | None = None,
|
||||
channel_name: str | None = None,
|
||||
) -> HostedRunResult:
|
||||
result = HostedRunResult(_FakeAgentResponse(text="hi"))
|
||||
if response_hook is None:
|
||||
return result
|
||||
shaped = response_hook(result, request=_request, channel_name=channel_name or _request.channel)
|
||||
if isinstance(shaped, Awaitable):
|
||||
return await shaped
|
||||
return shaped
|
||||
|
||||
ch._ctx = _Ctx() # type: ignore[assignment] # pyright: ignore[reportPrivateUsage]
|
||||
|
||||
@@ -213,42 +219,11 @@ class TestTelegramWebhook:
|
||||
args, kwargs = ch._http.post.call_args # type: ignore[attr-defined]
|
||||
assert args[0].endswith("/sendMessage")
|
||||
assert kwargs["json"]["text"] == "HI"
|
||||
assert contexts
|
||||
assert contexts[0].channel_name == "telegram"
|
||||
assert contexts[0].originating is True
|
||||
assert contexts[0].destination_identity is None
|
||||
assert seen_kwargs
|
||||
assert seen_kwargs[0]["channel_name"] == "telegram"
|
||||
|
||||
|
||||
class TestPushAndCommand:
|
||||
async def test_push_calls_send(self) -> None:
|
||||
ch, _agent = _make_telegram()
|
||||
from agent_framework_hosting import ChannelIdentity
|
||||
|
||||
await ch.push(ChannelIdentity(channel="telegram", native_id="42"), _run_result("hi"))
|
||||
assert ch._http is not None
|
||||
ch._http.post.assert_called() # type: ignore[attr-defined]
|
||||
args, kwargs = ch._http.post.call_args # type: ignore[attr-defined]
|
||||
assert args[0].endswith("/sendMessage")
|
||||
assert kwargs["json"]["chat_id"] in ("42", 42)
|
||||
assert kwargs["json"]["text"] == "hi"
|
||||
# Agent replies must stay loud: no silent flag on a non-echo push.
|
||||
assert "disable_notification" not in kwargs["json"]
|
||||
|
||||
async def test_push_echo_is_silent(self) -> None:
|
||||
ch, _agent = _make_telegram()
|
||||
from agent_framework_hosting import ChannelIdentity
|
||||
|
||||
echo = HostedRunResult(
|
||||
AgentResponse(messages=[Message(role="user", contents=[Content.from_text(text="said via X")])])
|
||||
)
|
||||
await ch.push(ChannelIdentity(channel="telegram", native_id="42"), echo)
|
||||
assert ch._http is not None
|
||||
_args, kwargs = ch._http.post.call_args # type: ignore[attr-defined]
|
||||
# Bots cannot impersonate the user (no MTProto send_as), so the echo is
|
||||
# delivered silently instead of buzzing the device like a real reply.
|
||||
assert kwargs["json"]["disable_notification"] is True
|
||||
assert kwargs["json"]["text"] == "said via X"
|
||||
|
||||
class TestCommand:
|
||||
async def test_command_handler_invoked(self) -> None:
|
||||
captured: list[ChannelCommandContext] = []
|
||||
|
||||
@@ -422,9 +397,7 @@ class TestShutdownDrainsWorkers:
|
||||
|
||||
|
||||
def _deletewebhook_called(http_mock: MagicMock) -> bool:
|
||||
return any(
|
||||
call.args and str(call.args[0]).endswith("/deleteWebhook") for call in http_mock.post.call_args_list
|
||||
)
|
||||
return any(call.args and str(call.args[0]).endswith("/deleteWebhook") for call in http_mock.post.call_args_list)
|
||||
|
||||
|
||||
class TestWebhookShutdownTeardown:
|
||||
|
||||
Reference in New Issue
Block a user