microsoft-agents-hosting-core 0.7.0__py3-none-any.whl → 0.7.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- microsoft_agents/hosting/core/__init__.py +1 -24
- microsoft_agents/hosting/core/app/agent_application.py +24 -12
- microsoft_agents/hosting/core/app/oauth/_sign_in_state.py +15 -7
- microsoft_agents/hosting/core/authorization/claims_identity.py +0 -14
- microsoft_agents/hosting/core/channel_service_adapter.py +14 -28
- microsoft_agents/hosting/core/connector/client/connector_client.py +1 -0
- microsoft_agents/hosting/core/connector/client/user_token_client.py +1 -0
- microsoft_agents/hosting/core/rest_channel_service_client_factory.py +2 -2
- microsoft_agents/hosting/core/storage/memory_storage.py +1 -0
- microsoft_agents/hosting/core/storage/storage.py +1 -0
- microsoft_agents/hosting/core/storage/transcript_logger.py +1 -0
- {microsoft_agents_hosting_core-0.7.0.dist-info → microsoft_agents_hosting_core-0.7.0.dev0.dist-info}/METADATA +3 -21
- {microsoft_agents_hosting_core-0.7.0.dist-info → microsoft_agents_hosting_core-0.7.0.dev0.dist-info}/RECORD +16 -25
- microsoft_agents/hosting/core/app/streaming/__init__.py +0 -14
- microsoft_agents/hosting/core/app/streaming/citation.py +0 -22
- microsoft_agents/hosting/core/app/streaming/citation_util.py +0 -85
- microsoft_agents/hosting/core/app/streaming/streaming_response.py +0 -411
- microsoft_agents/hosting/core/http/__init__.py +0 -17
- microsoft_agents/hosting/core/http/_channel_service_routes.py +0 -202
- microsoft_agents/hosting/core/http/_http_adapter_base.py +0 -136
- microsoft_agents/hosting/core/http/_http_request_protocol.py +0 -36
- microsoft_agents/hosting/core/http/_http_response.py +0 -56
- {microsoft_agents_hosting_core-0.7.0.dist-info → microsoft_agents_hosting_core-0.7.0.dev0.dist-info}/WHEEL +0 -0
- {microsoft_agents_hosting_core-0.7.0.dist-info → microsoft_agents_hosting_core-0.7.0.dev0.dist-info}/licenses/LICENSE +0 -0
- {microsoft_agents_hosting_core-0.7.0.dist-info → microsoft_agents_hosting_core-0.7.0.dev0.dist-info}/top_level.txt +0 -0
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
-
# Licensed under the MIT License.
|
|
3
|
-
|
|
4
|
-
"""Base HTTP adapter with shared processing logic."""
|
|
5
|
-
|
|
6
|
-
from abc import ABC
|
|
7
|
-
from traceback import format_exc
|
|
8
|
-
|
|
9
|
-
from microsoft_agents.activity import Activity, DeliveryModes
|
|
10
|
-
from microsoft_agents.hosting.core.authorization import ClaimsIdentity, Connections
|
|
11
|
-
from microsoft_agents.hosting.core import (
|
|
12
|
-
Agent,
|
|
13
|
-
ChannelServiceAdapter,
|
|
14
|
-
ChannelServiceClientFactoryBase,
|
|
15
|
-
MessageFactory,
|
|
16
|
-
RestChannelServiceClientFactory,
|
|
17
|
-
TurnContext,
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
from ._http_request_protocol import HttpRequestProtocol
|
|
21
|
-
from ._http_response import HttpResponse, HttpResponseFactory
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class HttpAdapterBase(ChannelServiceAdapter, ABC):
|
|
25
|
-
"""Base adapter for HTTP-based agent hosting with shared processing logic.
|
|
26
|
-
|
|
27
|
-
This class contains all the common logic for processing HTTP requests
|
|
28
|
-
and can be subclassed by framework-specific adapters (aiohttp, FastAPI, etc).
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
def __init__(
|
|
32
|
-
self,
|
|
33
|
-
*,
|
|
34
|
-
connection_manager: Connections = None,
|
|
35
|
-
channel_service_client_factory: ChannelServiceClientFactoryBase = None,
|
|
36
|
-
):
|
|
37
|
-
"""Initialize the HTTP adapter.
|
|
38
|
-
|
|
39
|
-
Args:
|
|
40
|
-
connection_manager: Optional connection manager for OAuth.
|
|
41
|
-
channel_service_client_factory: Factory for creating channel service clients.
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
async def on_turn_error(context: TurnContext, error: Exception):
|
|
45
|
-
error_message = f"Exception caught : {error}"
|
|
46
|
-
print(format_exc())
|
|
47
|
-
|
|
48
|
-
await context.send_activity(MessageFactory.text(error_message))
|
|
49
|
-
|
|
50
|
-
# Send a trace activity
|
|
51
|
-
await context.send_trace_activity(
|
|
52
|
-
"OnTurnError Trace",
|
|
53
|
-
error_message,
|
|
54
|
-
"https://www.botframework.com/schemas/error",
|
|
55
|
-
"TurnError",
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
self.on_turn_error = on_turn_error
|
|
59
|
-
|
|
60
|
-
channel_service_client_factory = (
|
|
61
|
-
channel_service_client_factory
|
|
62
|
-
or RestChannelServiceClientFactory(connection_manager)
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
super().__init__(channel_service_client_factory)
|
|
66
|
-
|
|
67
|
-
async def process_request(
|
|
68
|
-
self, request: HttpRequestProtocol, agent: Agent
|
|
69
|
-
) -> HttpResponse:
|
|
70
|
-
"""Process an incoming HTTP request.
|
|
71
|
-
|
|
72
|
-
Args:
|
|
73
|
-
request: The HTTP request to process.
|
|
74
|
-
agent: The agent to handle the request.
|
|
75
|
-
|
|
76
|
-
Returns:
|
|
77
|
-
HttpResponse with the result.
|
|
78
|
-
|
|
79
|
-
Raises:
|
|
80
|
-
TypeError: If request or agent is None.
|
|
81
|
-
"""
|
|
82
|
-
if not request:
|
|
83
|
-
raise TypeError("HttpAdapterBase.process_request: request can't be None")
|
|
84
|
-
if not agent:
|
|
85
|
-
raise TypeError("HttpAdapterBase.process_request: agent can't be None")
|
|
86
|
-
|
|
87
|
-
if request.method != "POST":
|
|
88
|
-
return HttpResponseFactory.method_not_allowed()
|
|
89
|
-
|
|
90
|
-
# Deserialize the incoming Activity
|
|
91
|
-
content_type = request.headers.get("Content-Type", "")
|
|
92
|
-
if "application/json" not in content_type:
|
|
93
|
-
return HttpResponseFactory.unsupported_media_type()
|
|
94
|
-
|
|
95
|
-
try:
|
|
96
|
-
body = await request.json()
|
|
97
|
-
except Exception:
|
|
98
|
-
return HttpResponseFactory.bad_request("Invalid JSON")
|
|
99
|
-
|
|
100
|
-
activity: Activity = Activity.model_validate(body)
|
|
101
|
-
|
|
102
|
-
# Get claims identity (default to anonymous if not set by middleware)
|
|
103
|
-
claims_identity: ClaimsIdentity = (
|
|
104
|
-
request.get_claims_identity() or ClaimsIdentity({}, False)
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
# Validate required activity fields
|
|
108
|
-
if (
|
|
109
|
-
not activity.type
|
|
110
|
-
or not activity.conversation
|
|
111
|
-
or not activity.conversation.id
|
|
112
|
-
):
|
|
113
|
-
return HttpResponseFactory.bad_request(
|
|
114
|
-
"Activity must have type and conversation.id"
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
try:
|
|
118
|
-
# Process the inbound activity with the agent
|
|
119
|
-
invoke_response = await self.process_activity(
|
|
120
|
-
claims_identity, activity, agent.on_turn
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
# Check if we need to return a synchronous response
|
|
124
|
-
if (
|
|
125
|
-
activity.type == "invoke"
|
|
126
|
-
or activity.delivery_mode == DeliveryModes.expect_replies
|
|
127
|
-
):
|
|
128
|
-
# Invoke and ExpectReplies cannot be performed async
|
|
129
|
-
return HttpResponseFactory.json(
|
|
130
|
-
invoke_response.body, invoke_response.status
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
return HttpResponseFactory.accepted()
|
|
134
|
-
|
|
135
|
-
except PermissionError:
|
|
136
|
-
return HttpResponseFactory.unauthorized()
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
-
# Licensed under the MIT License.
|
|
3
|
-
|
|
4
|
-
"""Protocol for abstracting HTTP request objects across frameworks."""
|
|
5
|
-
|
|
6
|
-
from typing import Protocol, Dict, Any, Optional
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class HttpRequestProtocol(Protocol):
|
|
10
|
-
"""Protocol for HTTP requests that adapters must implement.
|
|
11
|
-
|
|
12
|
-
This protocol defines the interface that framework-specific request
|
|
13
|
-
adapters must implement to work with the shared HTTP adapter logic.
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
@property
|
|
17
|
-
def method(self) -> str:
|
|
18
|
-
"""HTTP method (GET, POST, etc.)."""
|
|
19
|
-
...
|
|
20
|
-
|
|
21
|
-
@property
|
|
22
|
-
def headers(self) -> Dict[str, str]:
|
|
23
|
-
"""Request headers."""
|
|
24
|
-
...
|
|
25
|
-
|
|
26
|
-
async def json(self) -> Dict[str, Any]:
|
|
27
|
-
"""Parse request body as JSON."""
|
|
28
|
-
...
|
|
29
|
-
|
|
30
|
-
def get_claims_identity(self) -> Optional[Any]:
|
|
31
|
-
"""Get claims identity attached by auth middleware."""
|
|
32
|
-
...
|
|
33
|
-
|
|
34
|
-
def get_path_param(self, name: str) -> str:
|
|
35
|
-
"""Get path parameter by name."""
|
|
36
|
-
...
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
-
# Licensed under the MIT License.
|
|
3
|
-
|
|
4
|
-
"""HTTP response abstraction."""
|
|
5
|
-
|
|
6
|
-
from typing import Any, Optional, Dict
|
|
7
|
-
from dataclasses import dataclass
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@dataclass
|
|
11
|
-
class HttpResponse:
|
|
12
|
-
"""Framework-agnostic HTTP response."""
|
|
13
|
-
|
|
14
|
-
status_code: int
|
|
15
|
-
body: Optional[Any] = None
|
|
16
|
-
headers: Optional[Dict[str, str]] = None
|
|
17
|
-
content_type: Optional[str] = "application/json"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class HttpResponseFactory:
|
|
21
|
-
"""Factory for creating HTTP responses."""
|
|
22
|
-
|
|
23
|
-
@staticmethod
|
|
24
|
-
def ok(body: Any = None) -> HttpResponse:
|
|
25
|
-
"""Create 200 OK response."""
|
|
26
|
-
return HttpResponse(status_code=200, body=body)
|
|
27
|
-
|
|
28
|
-
@staticmethod
|
|
29
|
-
def accepted() -> HttpResponse:
|
|
30
|
-
"""Create 202 Accepted response."""
|
|
31
|
-
return HttpResponse(status_code=202)
|
|
32
|
-
|
|
33
|
-
@staticmethod
|
|
34
|
-
def json(body: Any, status_code: int = 200) -> HttpResponse:
|
|
35
|
-
"""Create JSON response."""
|
|
36
|
-
return HttpResponse(status_code=status_code, body=body)
|
|
37
|
-
|
|
38
|
-
@staticmethod
|
|
39
|
-
def bad_request(message: str = "Bad Request") -> HttpResponse:
|
|
40
|
-
"""Create 400 Bad Request response."""
|
|
41
|
-
return HttpResponse(status_code=400, body={"error": message})
|
|
42
|
-
|
|
43
|
-
@staticmethod
|
|
44
|
-
def unauthorized(message: str = "Unauthorized") -> HttpResponse:
|
|
45
|
-
"""Create 401 Unauthorized response."""
|
|
46
|
-
return HttpResponse(status_code=401, body={"error": message})
|
|
47
|
-
|
|
48
|
-
@staticmethod
|
|
49
|
-
def method_not_allowed(message: str = "Method Not Allowed") -> HttpResponse:
|
|
50
|
-
"""Create 405 Method Not Allowed response."""
|
|
51
|
-
return HttpResponse(status_code=405, body={"error": message})
|
|
52
|
-
|
|
53
|
-
@staticmethod
|
|
54
|
-
def unsupported_media_type(message: str = "Unsupported Media Type") -> HttpResponse:
|
|
55
|
-
"""Create 415 Unsupported Media Type response."""
|
|
56
|
-
return HttpResponse(status_code=415, body={"error": message})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|