uagents-core 0.3.5__tar.gz → 0.3.7__tar.gz
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.
- {uagents_core-0.3.5 → uagents_core-0.3.7}/PKG-INFO +1 -1
- {uagents_core-0.3.5 → uagents_core-0.3.7}/pyproject.toml +1 -1
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/contrib/protocols/chat/__init__.py +54 -1
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/types.py +2 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/utils/messages.py +83 -21
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/utils/resolver.py +10 -3
- {uagents_core-0.3.5 → uagents_core-0.3.7}/README.md +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/__init__.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/config.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/contrib/__init__.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/contrib/protocols/__init__.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/contrib/protocols/subscriptions/__init__.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/envelope.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/helpers.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/identity.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/logger.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/models.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/protocol.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/registration.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/storage.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/utils/__init__.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/utils/registration.py +0 -0
- {uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/utils/subscriptions.py +0 -0
@@ -2,8 +2,9 @@
|
|
2
2
|
This module contains the protocol specification for the agent chat protocol.
|
3
3
|
"""
|
4
4
|
|
5
|
-
from datetime import datetime
|
5
|
+
from datetime import datetime, timezone
|
6
6
|
from typing import Literal, TypedDict
|
7
|
+
from uuid import uuid4
|
7
8
|
|
8
9
|
from pydantic.v1 import UUID4
|
9
10
|
|
@@ -27,6 +28,9 @@ class TextContent(Model):
|
|
27
28
|
# markdown based formatting can be used and will be supported by most clients
|
28
29
|
text: str
|
29
30
|
|
31
|
+
def __init__(self, text: str, type: str = "text"):
|
32
|
+
super().__init__(type=type, text=text)
|
33
|
+
|
30
34
|
|
31
35
|
class Resource(Model):
|
32
36
|
# the uri of the resource
|
@@ -36,6 +40,9 @@ class Resource(Model):
|
|
36
40
|
# fields see `docs/metadata.md`
|
37
41
|
metadata: dict[str, str]
|
38
42
|
|
43
|
+
def __init__(self, uri: str, metadata: dict[str, str] | None = None):
|
44
|
+
super().__init__(uri=uri, metadata=metadata or {})
|
45
|
+
|
39
46
|
|
40
47
|
class ResourceContent(Model):
|
41
48
|
type: Literal["resource"]
|
@@ -51,6 +58,14 @@ class ResourceContent(Model):
|
|
51
58
|
# considered the primary resource
|
52
59
|
resource: Resource | list[Resource]
|
53
60
|
|
61
|
+
def __init__(
|
62
|
+
self,
|
63
|
+
resource_id: UUID4,
|
64
|
+
resource: Resource | list[Resource],
|
65
|
+
type: str = "resource",
|
66
|
+
):
|
67
|
+
super().__init__(type=type, resource_id=resource_id, resource=resource)
|
68
|
+
|
54
69
|
|
55
70
|
class MetadataContent(Model):
|
56
71
|
type: Literal["metadata"]
|
@@ -59,26 +74,41 @@ class MetadataContent(Model):
|
|
59
74
|
# fields see `docs/metadata.md`
|
60
75
|
metadata: dict[str, str]
|
61
76
|
|
77
|
+
def __init__(self, metadata: dict[str, str], type: str = "metadata"):
|
78
|
+
super().__init__(type=type, metadata=metadata)
|
79
|
+
|
62
80
|
|
63
81
|
class StartSessionContent(Model):
|
64
82
|
type: Literal["start-session"]
|
65
83
|
|
84
|
+
def __init__(self, type: str = "start-session"):
|
85
|
+
super().__init__(type=type)
|
86
|
+
|
66
87
|
|
67
88
|
class EndSessionContent(Model):
|
68
89
|
type: Literal["end-session"]
|
69
90
|
|
91
|
+
def __init__(self, type: str = "end-session"):
|
92
|
+
super().__init__(type=type)
|
93
|
+
|
70
94
|
|
71
95
|
class StartStreamContent(Model):
|
72
96
|
type: Literal["start-stream"]
|
73
97
|
|
74
98
|
stream_id: UUID4
|
75
99
|
|
100
|
+
def __init__(self, stream_id: UUID4, type: str = "start-stream"):
|
101
|
+
super().__init__(type=type, stream_id=stream_id)
|
102
|
+
|
76
103
|
|
77
104
|
class EndStreamContent(Model):
|
78
105
|
type: Literal["end-stream"]
|
79
106
|
|
80
107
|
stream_id: UUID4
|
81
108
|
|
109
|
+
def __init__(self, stream_id: UUID4, type: str = "end-stream"):
|
110
|
+
super().__init__(type=type, stream_id=stream_id)
|
111
|
+
|
82
112
|
|
83
113
|
# The combined agent content types
|
84
114
|
AgentContent = (
|
@@ -102,6 +132,16 @@ class ChatMessage(Model):
|
|
102
132
|
# the list of content elements in the chat
|
103
133
|
content: list[AgentContent]
|
104
134
|
|
135
|
+
def __init__(
|
136
|
+
self,
|
137
|
+
content: list[AgentContent],
|
138
|
+
msg_id: UUID4 | None = None,
|
139
|
+
timestamp: datetime | None = None,
|
140
|
+
):
|
141
|
+
msg_id = msg_id or uuid4()
|
142
|
+
timestamp = timestamp or datetime.now(timezone.utc)
|
143
|
+
super().__init__(timestamp=timestamp, msg_id=msg_id, content=content)
|
144
|
+
|
105
145
|
|
106
146
|
class ChatAcknowledgement(Model):
|
107
147
|
# the timestamp for the message, should be in UTC
|
@@ -113,6 +153,19 @@ class ChatAcknowledgement(Model):
|
|
113
153
|
# optional acknowledgement metadata
|
114
154
|
metadata: dict[str, str] | None = None
|
115
155
|
|
156
|
+
def __init__(
|
157
|
+
self,
|
158
|
+
acknowledged_msg_id: UUID4,
|
159
|
+
metadata: dict[str, str] | None = None,
|
160
|
+
timestamp: datetime | None = None,
|
161
|
+
):
|
162
|
+
timestamp = timestamp or datetime.now(timezone.utc)
|
163
|
+
super().__init__(
|
164
|
+
timestamp=timestamp,
|
165
|
+
acknowledged_msg_id=acknowledged_msg_id,
|
166
|
+
metadata=metadata,
|
167
|
+
)
|
168
|
+
|
116
169
|
|
117
170
|
chat_protocol_spec = ProtocolSpecification(
|
118
171
|
name="AgentChatProtocol",
|
@@ -2,19 +2,24 @@
|
|
2
2
|
This module provides methods to enable an identity to interact with other agents.
|
3
3
|
"""
|
4
4
|
|
5
|
+
import contextlib
|
5
6
|
import json
|
6
7
|
from typing import Any, Literal
|
7
8
|
from uuid import UUID, uuid4
|
8
9
|
|
9
10
|
import requests
|
11
|
+
from pydantic import ValidationError
|
10
12
|
|
11
|
-
from uagents_core.config import
|
13
|
+
from uagents_core.config import (
|
14
|
+
DEFAULT_MAX_ENDPOINTS,
|
15
|
+
DEFAULT_REQUEST_TIMEOUT,
|
16
|
+
AgentverseConfig,
|
17
|
+
)
|
12
18
|
from uagents_core.envelope import Envelope
|
13
|
-
from uagents_core.helpers import weighted_random_sample
|
14
19
|
from uagents_core.identity import Identity
|
15
20
|
from uagents_core.logger import get_logger
|
16
21
|
from uagents_core.models import Model
|
17
|
-
from uagents_core.types import DeliveryStatus, MsgStatus, Resolver
|
22
|
+
from uagents_core.types import DeliveryStatus, JsonStr, MsgStatus, Resolver
|
18
23
|
from uagents_core.utils.resolver import AlmanacResolver
|
19
24
|
|
20
25
|
logger = get_logger("uagents_core.utils.messages")
|
@@ -58,7 +63,10 @@ def generate_message_envelope(
|
|
58
63
|
|
59
64
|
|
60
65
|
def send_message(
|
61
|
-
endpoint: str,
|
66
|
+
endpoint: str,
|
67
|
+
envelope: Envelope,
|
68
|
+
timeout: int = DEFAULT_REQUEST_TIMEOUT,
|
69
|
+
sync: bool = False,
|
62
70
|
) -> requests.Response:
|
63
71
|
"""
|
64
72
|
A helper function to send a message to an agent.
|
@@ -67,13 +75,17 @@ def send_message(
|
|
67
75
|
endpoint (str): The endpoint to send the message to.
|
68
76
|
envelope (Envelope): The envelope containing the message.
|
69
77
|
timeout (int, optional): Requests timeout. Defaults to DEFAULT_REQUEST_TIMEOUT.
|
78
|
+
sync (bool, optional): Whether to send the message synchronously. Defaults to False.
|
70
79
|
|
71
80
|
Returns:
|
72
81
|
requests.Response: Response object from the request.
|
73
82
|
"""
|
83
|
+
headers = {"content-type": "application/json"}
|
84
|
+
if sync:
|
85
|
+
headers["x-uagents-connection"] = "sync"
|
74
86
|
response = requests.post(
|
75
87
|
url=endpoint,
|
76
|
-
headers=
|
88
|
+
headers=headers,
|
77
89
|
data=envelope.model_dump_json(),
|
78
90
|
timeout=timeout,
|
79
91
|
)
|
@@ -81,6 +93,39 @@ def send_message(
|
|
81
93
|
return response
|
82
94
|
|
83
95
|
|
96
|
+
def parse_sync_response(
|
97
|
+
env_json: JsonStr,
|
98
|
+
response_type: type[Model] | set[type[Model]] | None = None,
|
99
|
+
) -> Model | JsonStr:
|
100
|
+
"""
|
101
|
+
Parse the response from a synchronous message.
|
102
|
+
|
103
|
+
Args:
|
104
|
+
env_json (JsonStr): The JSON string of the response envelope.
|
105
|
+
response_type (type[Model] | set[type[Model]] | None, optional):
|
106
|
+
The expected response type(s) for a sync message.
|
107
|
+
|
108
|
+
Returns:
|
109
|
+
Model | JsonStr: The parsed response model or JSON string.
|
110
|
+
"""
|
111
|
+
|
112
|
+
env = Envelope.model_validate_json(env_json)
|
113
|
+
|
114
|
+
response_json = env.decode_payload()
|
115
|
+
|
116
|
+
response_msg: Model | None = None
|
117
|
+
if response_type:
|
118
|
+
response_types = (
|
119
|
+
{response_type} if isinstance(response_type, type) else response_type
|
120
|
+
)
|
121
|
+
|
122
|
+
for r_type in response_types:
|
123
|
+
with contextlib.suppress(ValidationError):
|
124
|
+
response_msg = r_type.parse_raw(response_json)
|
125
|
+
|
126
|
+
return response_msg or response_json
|
127
|
+
|
128
|
+
|
84
129
|
def send_message_to_agent(
|
85
130
|
destination: str,
|
86
131
|
msg: Model,
|
@@ -90,7 +135,9 @@ def send_message_to_agent(
|
|
90
135
|
strategy: Literal["first", "random", "all"] = "first",
|
91
136
|
agentverse_config: AgentverseConfig | None = None,
|
92
137
|
resolver: Resolver | None = None,
|
93
|
-
|
138
|
+
sync: bool = False,
|
139
|
+
response_type: type[Model] | set[type[Model]] | None = None,
|
140
|
+
) -> list[MsgStatus] | Model | JsonStr:
|
94
141
|
"""
|
95
142
|
Send a message to an agent with default settings.
|
96
143
|
|
@@ -102,11 +149,21 @@ def send_message_to_agent(
|
|
102
149
|
strategy (Literal["first", "random", "all"], optional): The strategy to use when
|
103
150
|
selecting an endpoint.
|
104
151
|
agentverse_config (AgentverseConfig, optional): The configuration for the agentverse.
|
152
|
+
resolver (Resolver, optional): The resolver to use for finding endpoints.
|
153
|
+
sync (bool, optional): Whether to send the message synchronously and wait for a response.
|
154
|
+
response_type (type[Model] | set[type[Model]] | None, optional):
|
155
|
+
The expected response type(s) for a sync message.
|
156
|
+
|
157
|
+
Returns:
|
158
|
+
list[MsgStatus] | Model | JsonStr: A list of message statuses
|
159
|
+
or the response model or json string if sync is True.
|
105
160
|
"""
|
106
161
|
agentverse_config = agentverse_config or AgentverseConfig()
|
107
162
|
|
108
163
|
if not resolver:
|
164
|
+
max_endpoints = 1 if strategy in ["first", "random"] else DEFAULT_MAX_ENDPOINTS
|
109
165
|
resolver = AlmanacResolver(
|
166
|
+
max_endpoints=max_endpoints,
|
110
167
|
agentverse_config=agentverse_config,
|
111
168
|
)
|
112
169
|
endpoints = resolver.sync_resolve(destination)
|
@@ -121,31 +178,24 @@ def send_message_to_agent(
|
|
121
178
|
sender=sender,
|
122
179
|
session_id=session_id,
|
123
180
|
)
|
124
|
-
match strategy:
|
125
|
-
case "first":
|
126
|
-
endpoints = endpoints[:1]
|
127
|
-
case "random":
|
128
|
-
endpoints = weighted_random_sample(endpoints)
|
129
|
-
|
130
|
-
endpoints: list[str] = endpoints if strategy == "all" else endpoints[:1]
|
131
181
|
|
132
|
-
|
182
|
+
status_result: list[MsgStatus] = []
|
133
183
|
for endpoint in endpoints:
|
134
184
|
try:
|
135
|
-
response = send_message(endpoint, env)
|
136
|
-
|
137
|
-
result.append(
|
185
|
+
response = send_message(endpoint, env, sync=True)
|
186
|
+
status_result.append(
|
138
187
|
MsgStatus(
|
139
188
|
status=DeliveryStatus.SENT,
|
140
|
-
detail=
|
189
|
+
detail="Message sent successfully",
|
141
190
|
destination=destination,
|
142
191
|
endpoint=endpoint,
|
143
|
-
session=
|
192
|
+
session=session_id,
|
144
193
|
)
|
145
194
|
)
|
195
|
+
break
|
146
196
|
except requests.RequestException as e:
|
147
197
|
logger.error("Failed to send message to agent", extra={"error": str(e)})
|
148
|
-
|
198
|
+
status_result.append(
|
149
199
|
MsgStatus(
|
150
200
|
status=DeliveryStatus.FAILED,
|
151
201
|
detail=str(e),
|
@@ -154,4 +204,16 @@ def send_message_to_agent(
|
|
154
204
|
session=env.session,
|
155
205
|
)
|
156
206
|
)
|
157
|
-
|
207
|
+
|
208
|
+
logger.info("Sent message to agent", extra={"agent_endpoint": endpoint})
|
209
|
+
|
210
|
+
if sync:
|
211
|
+
try:
|
212
|
+
return parse_sync_response(response.text, response_type)
|
213
|
+
except ValidationError as e:
|
214
|
+
logger.error(
|
215
|
+
"Received invalid response envelope",
|
216
|
+
extra={"error": str(e), "response": response.text},
|
217
|
+
)
|
218
|
+
|
219
|
+
return status_result
|
@@ -75,17 +75,24 @@ def lookup_endpoint_for_agent(
|
|
75
75
|
|
76
76
|
|
77
77
|
class AlmanacResolver(Resolver):
|
78
|
-
def __init__(
|
78
|
+
def __init__(
|
79
|
+
self, max_endpoints: int = 1, agentverse_config: AgentverseConfig | None = None
|
80
|
+
):
|
79
81
|
self.agentverse_config = agentverse_config or AgentverseConfig()
|
82
|
+
self.max_endpoints = max_endpoints
|
80
83
|
|
81
84
|
async def resolve(self, destination: str) -> tuple[str | None, list[str]]:
|
82
85
|
endpoints = lookup_endpoint_for_agent(
|
83
|
-
agent_identifier=destination,
|
86
|
+
agent_identifier=destination,
|
87
|
+
max_endpoints=self.max_endpoints,
|
88
|
+
agentverse_config=self.agentverse_config,
|
84
89
|
)
|
85
90
|
return None, endpoints
|
86
91
|
|
87
92
|
def sync_resolve(self, destination: str) -> list[str]:
|
88
93
|
endpoints = lookup_endpoint_for_agent(
|
89
|
-
agent_identifier=destination,
|
94
|
+
agent_identifier=destination,
|
95
|
+
max_endpoints=self.max_endpoints,
|
96
|
+
agentverse_config=self.agentverse_config,
|
90
97
|
)
|
91
98
|
return endpoints
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{uagents_core-0.3.5 → uagents_core-0.3.7}/uagents_core/contrib/protocols/subscriptions/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|