uagents-core 0.1.2__py3-none-any.whl → 0.2.0__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.
- uagents_core/config.py +12 -1
- uagents_core/contrib/protocols/chat/__init__.py +124 -0
- uagents_core/contrib/protocols/subscriptions/__init__.py +75 -0
- uagents_core/envelope.py +19 -71
- uagents_core/helpers.py +30 -0
- uagents_core/{crypto.py → identity.py} +57 -7
- uagents_core/logger.py +32 -33
- uagents_core/models.py +9 -5
- uagents_core/protocol.py +166 -0
- uagents_core/registration.py +50 -19
- uagents_core/types.py +38 -2
- uagents_core/utils/__init__.py +5 -0
- uagents_core/utils/messages.py +153 -0
- uagents_core/utils/registration.py +148 -100
- uagents_core/utils/resolver.py +73 -0
- {uagents_core-0.1.2.dist-info → uagents_core-0.2.0.dist-info}/METADATA +11 -11
- uagents_core-0.2.0.dist-info/RECORD +19 -0
- {uagents_core-0.1.2.dist-info → uagents_core-0.2.0.dist-info}/WHEEL +1 -1
- uagents_core/communication.py +0 -76
- uagents_core/utils/communication.py +0 -130
- uagents_core-0.1.2.dist-info/RECORD +0 -15
@@ -1,16 +1,22 @@
|
|
1
|
+
"""
|
2
|
+
This module provides methods to register your identity with the Fetch.ai services.
|
3
|
+
"""
|
4
|
+
|
1
5
|
import urllib.parse
|
2
|
-
from typing import List, Optional
|
3
6
|
|
4
7
|
import requests
|
8
|
+
from pydantic import BaseModel
|
5
9
|
|
6
10
|
from uagents_core.config import (
|
7
11
|
DEFAULT_ALMANAC_API_PATH,
|
8
12
|
DEFAULT_CHALLENGE_PATH,
|
9
13
|
DEFAULT_REGISTRATION_PATH,
|
14
|
+
DEFAULT_REQUEST_TIMEOUT,
|
10
15
|
AgentverseConfig,
|
11
16
|
)
|
12
|
-
from uagents_core.
|
17
|
+
from uagents_core.identity import Identity
|
13
18
|
from uagents_core.logger import get_logger
|
19
|
+
from uagents_core.protocol import is_valid_protocol_digest
|
14
20
|
from uagents_core.registration import (
|
15
21
|
AgentRegistrationAttestation,
|
16
22
|
AgentUpdates,
|
@@ -25,22 +31,77 @@ from uagents_core.types import AgentEndpoint
|
|
25
31
|
logger = get_logger("uagents_core.utils.registration")
|
26
32
|
|
27
33
|
|
34
|
+
def _send_post_request(
|
35
|
+
url: str,
|
36
|
+
data: BaseModel,
|
37
|
+
*,
|
38
|
+
headers: dict[str, str] | None = None,
|
39
|
+
timeout: int = DEFAULT_REQUEST_TIMEOUT,
|
40
|
+
) -> tuple[bool, requests.Response | None]:
|
41
|
+
final_headers: dict[str, str] = {"content-type": "application/json"}
|
42
|
+
if headers:
|
43
|
+
final_headers.update(headers)
|
44
|
+
try:
|
45
|
+
response: requests.Response = requests.post(
|
46
|
+
url=url,
|
47
|
+
headers=final_headers,
|
48
|
+
data=data.model_dump_json(),
|
49
|
+
timeout=timeout,
|
50
|
+
)
|
51
|
+
response.raise_for_status()
|
52
|
+
return True, response
|
53
|
+
except requests.RequestException as e:
|
54
|
+
logger.error(
|
55
|
+
msg="Error submitting request",
|
56
|
+
extra={"url": url, "data": data.model_dump_json()},
|
57
|
+
exc_info=e,
|
58
|
+
)
|
59
|
+
return False, None
|
60
|
+
|
61
|
+
|
28
62
|
def register_in_almanac(
|
29
|
-
request: AgentverseConnectRequest,
|
30
63
|
identity: Identity,
|
64
|
+
endpoints: list[str],
|
65
|
+
protocol_digests: list[str],
|
31
66
|
*,
|
32
|
-
|
33
|
-
|
34
|
-
):
|
67
|
+
agentverse_config: AgentverseConfig | None = None,
|
68
|
+
timeout: int = DEFAULT_REQUEST_TIMEOUT,
|
69
|
+
) -> bool:
|
35
70
|
"""
|
36
|
-
Register the
|
71
|
+
Register the identity with the Almanac API to make it discoverable by other agents.
|
37
72
|
|
38
73
|
Args:
|
39
|
-
request (AgentverseConnectRequest): The request containing the agent details.
|
40
74
|
identity (Identity): The identity of the agent.
|
41
|
-
|
75
|
+
endpoints (list[str]): The endpoints that the agent can be reached at.
|
76
|
+
protocol_digests (list[str]): The digests of the protocol that the agent supports
|
42
77
|
agentverse_config (AgentverseConfig): The configuration for the agentverse API
|
78
|
+
timeout (int): The timeout for the request
|
43
79
|
"""
|
80
|
+
# check endpoints
|
81
|
+
if not endpoints:
|
82
|
+
logger.warning("No endpoints provided; skipping registration")
|
83
|
+
return False
|
84
|
+
for endpoint in endpoints:
|
85
|
+
result = urllib.parse.urlparse(endpoint)
|
86
|
+
if not all([result.scheme, result.netloc]):
|
87
|
+
logger.error(
|
88
|
+
msg="Invalid endpoint provided; skipping registration",
|
89
|
+
extra={"endpoint": endpoint},
|
90
|
+
)
|
91
|
+
return False
|
92
|
+
|
93
|
+
agent_endpoints: list[AgentEndpoint] = [
|
94
|
+
AgentEndpoint(url=endpoint, weight=1) for endpoint in endpoints
|
95
|
+
]
|
96
|
+
|
97
|
+
# check protocol digests
|
98
|
+
for proto_digest in protocol_digests:
|
99
|
+
if not is_valid_protocol_digest(proto_digest):
|
100
|
+
logger.error(
|
101
|
+
msg="Invalid protocol digest provided; skipping registration",
|
102
|
+
extra={"protocol_digest": proto_digest},
|
103
|
+
)
|
104
|
+
return False
|
44
105
|
|
45
106
|
# get the almanac API endpoint
|
46
107
|
agentverse_config = agentverse_config or AgentverseConfig()
|
@@ -49,83 +110,51 @@ def register_in_almanac(
|
|
49
110
|
# get the agent address
|
50
111
|
agent_address = identity.address
|
51
112
|
|
52
|
-
registration_metadata = {
|
53
|
-
"almanac_endpoint": almanac_api,
|
54
|
-
"agent_address": agent_address,
|
55
|
-
"agent_endpoint": request.endpoint or "",
|
56
|
-
"protocol_digest": ",".join(protocol_digests),
|
57
|
-
}
|
58
|
-
if request.endpoint is None:
|
59
|
-
if request.agent_type == "mailbox":
|
60
|
-
request.endpoint = f"{agentverse_config.url}/v1/submit"
|
61
|
-
elif request.agent_type == "proxy":
|
62
|
-
request.endpoint = f"{agentverse_config.url}/v1/proxy/submit"
|
63
|
-
|
64
|
-
if request.endpoint is None:
|
65
|
-
logger.warning(
|
66
|
-
"No endpoint provided for agent registration",
|
67
|
-
extra=registration_metadata,
|
68
|
-
)
|
69
|
-
return
|
70
|
-
|
71
|
-
logger.info(
|
72
|
-
"Registering with Almanac API",
|
73
|
-
extra=registration_metadata,
|
74
|
-
)
|
75
|
-
|
76
113
|
# create the attestation
|
77
114
|
attestation = AgentRegistrationAttestation(
|
78
115
|
agent_identifier=agent_address,
|
79
116
|
protocols=protocol_digests,
|
80
|
-
endpoints=
|
81
|
-
AgentEndpoint(url=request.endpoint, weight=1),
|
82
|
-
],
|
117
|
+
endpoints=agent_endpoints,
|
83
118
|
metadata=None,
|
84
119
|
)
|
85
120
|
|
121
|
+
logger.info(msg="Registering with Almanac API", extra=attestation.model_dump())
|
122
|
+
|
86
123
|
# sign the attestation
|
87
124
|
attestation.sign(identity)
|
88
125
|
|
89
126
|
# submit the attestation to the API
|
90
|
-
|
91
|
-
f"{almanac_api}/agents",
|
92
|
-
headers={"content-type": "application/json"},
|
93
|
-
data=attestation.model_dump_json(),
|
94
|
-
)
|
95
|
-
r.raise_for_status()
|
96
|
-
logger.debug(
|
97
|
-
"Agent attestation submitted",
|
98
|
-
extra=registration_metadata,
|
127
|
+
status, _ = _send_post_request(
|
128
|
+
url=f"{almanac_api}/agents", data=attestation, timeout=timeout
|
99
129
|
)
|
130
|
+
return status
|
100
131
|
|
101
132
|
|
133
|
+
# associate user account with your agent
|
102
134
|
def register_in_agentverse(
|
103
135
|
request: AgentverseConnectRequest,
|
104
136
|
identity: Identity,
|
105
|
-
agent_details: Optional[AgentUpdates] = None,
|
106
137
|
*,
|
107
|
-
|
108
|
-
|
138
|
+
agent_details: AgentUpdates | None = None,
|
139
|
+
agentverse_config: AgentverseConfig | None = None,
|
140
|
+
timeout: int = DEFAULT_REQUEST_TIMEOUT,
|
141
|
+
) -> bool:
|
109
142
|
"""
|
110
|
-
Register
|
143
|
+
Register an agent in Agentverse and update its details if provided.
|
111
144
|
|
112
145
|
Args:
|
113
146
|
request (AgentverseConnectRequest): The request containing the agent details.
|
114
147
|
identity (Identity): The identity of the agent.
|
115
|
-
agent_details (
|
116
|
-
agentverse_config (AgentverseConfig): The configuration for the agentverse API
|
117
|
-
|
118
|
-
None
|
148
|
+
agent_details (AgentUpdates | None): The agent details to update.
|
149
|
+
agentverse_config (AgentverseConfig | None): The configuration for the agentverse API
|
150
|
+
timeout (int): The timeout for the requests
|
119
151
|
"""
|
120
|
-
|
121
|
-
# API endpoints
|
122
152
|
agentverse_config = agentverse_config or AgentverseConfig()
|
123
153
|
registration_api = urllib.parse.urljoin(
|
124
154
|
agentverse_config.url, DEFAULT_REGISTRATION_PATH
|
125
155
|
)
|
126
156
|
challenge_api = urllib.parse.urljoin(agentverse_config.url, DEFAULT_CHALLENGE_PATH)
|
127
157
|
|
128
|
-
# get the agent address
|
129
158
|
agent_address = identity.address
|
130
159
|
|
131
160
|
registration_metadata = {
|
@@ -138,87 +167,106 @@ def register_in_agentverse(
|
|
138
167
|
}
|
139
168
|
|
140
169
|
# check to see if the agent exists
|
141
|
-
|
170
|
+
response = requests.get(
|
142
171
|
f"{registration_api}/{agent_address}",
|
143
172
|
headers={
|
144
173
|
"content-type": "application/json",
|
145
174
|
"authorization": f"Bearer {request.user_token}",
|
146
175
|
},
|
176
|
+
timeout=timeout,
|
147
177
|
)
|
148
178
|
|
149
179
|
# if it doesn't then create it
|
150
|
-
if
|
180
|
+
if response.status_code == 404:
|
151
181
|
logger.debug(
|
152
|
-
"Agent
|
182
|
+
msg="Agent does not exist on agentverse; registering it...",
|
153
183
|
extra=registration_metadata,
|
154
184
|
)
|
155
185
|
|
156
186
|
challenge_request = ChallengeRequest(address=identity.address)
|
157
187
|
logger.debug(
|
158
|
-
"Requesting mailbox access challenge",
|
159
|
-
extra=registration_metadata,
|
188
|
+
msg="Requesting mailbox access challenge", extra=registration_metadata
|
160
189
|
)
|
161
|
-
|
162
|
-
challenge_api,
|
163
|
-
data=challenge_request
|
164
|
-
headers={
|
165
|
-
|
166
|
-
"Authorization": f"Bearer {request.user_token}",
|
167
|
-
},
|
190
|
+
status, response = _send_post_request(
|
191
|
+
url=challenge_api,
|
192
|
+
data=challenge_request,
|
193
|
+
headers={"authorization": f"Bearer {request.user_token}"},
|
194
|
+
timeout=timeout,
|
168
195
|
)
|
169
|
-
|
170
|
-
|
196
|
+
if not status or not response:
|
197
|
+
logger.error(
|
198
|
+
msg="Error requesting mailbox access challenge",
|
199
|
+
extra=registration_metadata,
|
200
|
+
)
|
201
|
+
return False
|
202
|
+
|
203
|
+
challenge = ChallengeResponse.model_validate_json(response.text)
|
171
204
|
registration_payload = RegistrationRequest(
|
172
205
|
address=identity.address,
|
173
206
|
challenge=challenge.challenge,
|
174
207
|
challenge_response=identity.sign(challenge.challenge.encode()),
|
175
208
|
endpoint=request.endpoint,
|
176
209
|
agent_type=request.agent_type,
|
177
|
-
)
|
178
|
-
|
179
|
-
registration_api,
|
180
|
-
headers={
|
181
|
-
"content-type": "application/json",
|
182
|
-
"authorization": f"Bearer {request.user_token}",
|
183
|
-
},
|
210
|
+
)
|
211
|
+
status, response = _send_post_request(
|
212
|
+
url=registration_api,
|
184
213
|
data=registration_payload,
|
214
|
+
headers={"authorization": f"Bearer {request.user_token}"},
|
215
|
+
timeout=timeout,
|
185
216
|
)
|
186
|
-
if
|
217
|
+
if not status or not response:
|
218
|
+
logger.error(
|
219
|
+
msg="Error registering agent with Agentverse",
|
220
|
+
extra=registration_metadata,
|
221
|
+
)
|
222
|
+
return False
|
223
|
+
if response.status_code == 409:
|
187
224
|
logger.info(
|
188
|
-
"Agent already registered with Agentverse",
|
225
|
+
msg="Agent already registered with Agentverse",
|
189
226
|
extra=registration_metadata,
|
190
227
|
)
|
191
228
|
else:
|
192
|
-
|
193
|
-
|
229
|
+
registration_response = RegistrationResponse.model_validate_json(
|
230
|
+
response.text
|
231
|
+
)
|
194
232
|
if registration_response.success:
|
195
233
|
logger.info(
|
196
|
-
f"Successfully registered as {request.agent_type} agent in Agentverse",
|
234
|
+
msg=f"Successfully registered as {request.agent_type} agent in Agentverse",
|
197
235
|
extra=registration_metadata,
|
198
236
|
)
|
237
|
+
|
199
238
|
if not agent_details:
|
200
239
|
logger.debug(
|
201
|
-
"No agent details provided; skipping agent update",
|
240
|
+
msg="No agent details provided; skipping agent update",
|
202
241
|
extra=registration_metadata,
|
203
242
|
)
|
204
|
-
return
|
243
|
+
return True
|
205
244
|
|
206
|
-
# update the readme and the
|
245
|
+
# update the readme and the name of the agent to make it easier to find
|
207
246
|
logger.debug(
|
208
|
-
"Registering agent
|
209
|
-
extra=registration_metadata,
|
210
|
-
)
|
211
|
-
update = AgentUpdates(name=agent_details.name, readme=agent_details.readme)
|
212
|
-
r = requests.put(
|
213
|
-
f"{registration_api}/{agent_address}",
|
214
|
-
headers={
|
215
|
-
"content-type": "application/json",
|
216
|
-
"authorization": f"Bearer {request.user_token}",
|
217
|
-
},
|
218
|
-
data=update.model_dump_json(),
|
219
|
-
)
|
220
|
-
r.raise_for_status()
|
221
|
-
logger.info(
|
222
|
-
"Completed registering agent with Agentverse",
|
247
|
+
msg="Registering agent details with Agentverse",
|
223
248
|
extra=registration_metadata,
|
224
249
|
)
|
250
|
+
try:
|
251
|
+
response = requests.put(
|
252
|
+
url=f"{registration_api}/{agent_address}",
|
253
|
+
headers={
|
254
|
+
"content-type": "application/json",
|
255
|
+
"authorization": f"Bearer {request.user_token}",
|
256
|
+
},
|
257
|
+
data=agent_details.model_dump_json(),
|
258
|
+
timeout=timeout,
|
259
|
+
)
|
260
|
+
response.raise_for_status()
|
261
|
+
logger.info(
|
262
|
+
msg="Completed registering agent with Agentverse",
|
263
|
+
extra=registration_metadata,
|
264
|
+
)
|
265
|
+
return True
|
266
|
+
except requests.RequestException as e:
|
267
|
+
logger.error(
|
268
|
+
msg="Error registering agent with Agentverse",
|
269
|
+
extra=registration_metadata,
|
270
|
+
exc_info=e,
|
271
|
+
)
|
272
|
+
return False
|
@@ -0,0 +1,73 @@
|
|
1
|
+
"""This module provides methods to resolve an agent address."""
|
2
|
+
|
3
|
+
import urllib.parse
|
4
|
+
from typing import Any
|
5
|
+
|
6
|
+
import requests
|
7
|
+
|
8
|
+
from uagents_core.config import (
|
9
|
+
DEFAULT_ALMANAC_API_PATH,
|
10
|
+
DEFAULT_MAX_ENDPOINTS,
|
11
|
+
DEFAULT_REQUEST_TIMEOUT,
|
12
|
+
AgentverseConfig,
|
13
|
+
)
|
14
|
+
from uagents_core.helpers import weighted_random_sample
|
15
|
+
from uagents_core.identity import parse_identifier
|
16
|
+
from uagents_core.logger import get_logger
|
17
|
+
|
18
|
+
logger = get_logger("uagents_core.utils.resolver")
|
19
|
+
|
20
|
+
|
21
|
+
def lookup_endpoint_for_agent(
|
22
|
+
agent_identifier: str,
|
23
|
+
*,
|
24
|
+
max_endpoints: int = DEFAULT_MAX_ENDPOINTS,
|
25
|
+
agentverse_config: AgentverseConfig | None = None,
|
26
|
+
) -> list[str]:
|
27
|
+
"""
|
28
|
+
Resolve the endpoints for an agent using the Almanac API.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
destination (str): The destination address to look up.
|
32
|
+
|
33
|
+
Returns:
|
34
|
+
List[str]: The endpoint(s) for the agent.
|
35
|
+
"""
|
36
|
+
_, _, agent_address = parse_identifier(agent_identifier)
|
37
|
+
|
38
|
+
agentverse_config = agentverse_config or AgentverseConfig()
|
39
|
+
almanac_api = urllib.parse.urljoin(agentverse_config.url, DEFAULT_ALMANAC_API_PATH)
|
40
|
+
|
41
|
+
request_meta: dict[str, Any] = {
|
42
|
+
"agent_address": agent_address,
|
43
|
+
"lookup_url": almanac_api,
|
44
|
+
}
|
45
|
+
logger.debug(msg="looking up endpoint for agent", extra=request_meta)
|
46
|
+
try:
|
47
|
+
response = requests.get(
|
48
|
+
url=f"{almanac_api}/agents/{agent_address}", timeout=DEFAULT_REQUEST_TIMEOUT
|
49
|
+
)
|
50
|
+
response.raise_for_status()
|
51
|
+
except requests.RequestException as e:
|
52
|
+
request_meta["exception"] = e
|
53
|
+
logger.error(msg="Error looking up agent endpoint", extra=request_meta)
|
54
|
+
return []
|
55
|
+
|
56
|
+
request_meta["response_status"] = response.status_code
|
57
|
+
logger.info(
|
58
|
+
msg="Got response looking up agent endpoint",
|
59
|
+
extra=request_meta,
|
60
|
+
)
|
61
|
+
|
62
|
+
endpoints: list = response.json().get("endpoints", [])
|
63
|
+
|
64
|
+
if len(endpoints) > 0:
|
65
|
+
urls = [val.get("url") for val in endpoints]
|
66
|
+
weights = [val.get("weight") for val in endpoints]
|
67
|
+
return weighted_random_sample(
|
68
|
+
items=urls,
|
69
|
+
weights=weights,
|
70
|
+
k=min(max_endpoints, len(endpoints)),
|
71
|
+
)
|
72
|
+
|
73
|
+
return []
|
@@ -1,27 +1,27 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: uagents-core
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.2.0
|
4
4
|
Summary: Core components for agent based systems
|
5
5
|
License: Apache 2.0
|
6
6
|
Author: Ed FitzGerald
|
7
7
|
Author-email: edward.fitzgerald@fetch.ai
|
8
|
-
Requires-Python: >=3.
|
8
|
+
Requires-Python: >=3.10,<4.0
|
9
9
|
Classifier: License :: Other/Proprietary License
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
11
|
-
Classifier: Programming Language :: Python :: 3.9
|
12
11
|
Classifier: Programming Language :: Python :: 3.10
|
13
12
|
Classifier: Programming Language :: Python :: 3.11
|
14
13
|
Classifier: Programming Language :: Python :: 3.12
|
15
|
-
|
16
|
-
Requires-Dist: bech32 (>=1.2.0,<2.0
|
17
|
-
Requires-Dist: ecdsa (>=0.19.0,<
|
18
|
-
Requires-Dist:
|
19
|
-
Requires-Dist: pydantic (>=2.8,<2.9)
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
15
|
+
Requires-Dist: bech32 (>=1.2.0,<2.0)
|
16
|
+
Requires-Dist: ecdsa (>=0.19.0,<1.0)
|
17
|
+
Requires-Dist: pydantic (>=2.8,<3.0)
|
20
18
|
Requires-Dist: requests (>=2.32.3,<3.0)
|
21
|
-
|
22
|
-
|
19
|
+
Project-URL: Documentation, https://fetch.ai/docs
|
20
|
+
Project-URL: Homepage, https://fetch.ai
|
21
|
+
Project-URL: Repository, https://github.com/fetchai/uAgents
|
23
22
|
Description-Content-Type: text/markdown
|
24
23
|
|
25
|
-
#
|
24
|
+
# uAgents-Core
|
26
25
|
|
27
26
|
Core definitions and functionalities to build agent which can interact and integrate with Fetch.ai ecosystem and agent marketplace.
|
27
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
uagents_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
uagents_core/config.py,sha256=mvCXtvt_efDbmoTcw0JNHymWZGOtXxIYXlrooWfbY1Q,798
|
3
|
+
uagents_core/contrib/protocols/chat/__init__.py,sha256=EAt2uQeaZtrSEdt2SiFyqFcC4nxKtyoJRaHhjKtwngw,3032
|
4
|
+
uagents_core/contrib/protocols/subscriptions/__init__.py,sha256=HsxWzLOvP83a7RkHRx8y_uXTJzJtuuBcyRNj33TT7xA,1944
|
5
|
+
uagents_core/envelope.py,sha256=eGq-Te-z2nRQVJIPqRdf-h48hGwg7IOKptIQZKYKqFU,3527
|
6
|
+
uagents_core/helpers.py,sha256=Nfl3V5Vl_23O4Ewtwlsh0v5rxthkZPm6b4BvsLGDKn8,943
|
7
|
+
uagents_core/identity.py,sha256=YHI3rromJ27DGF3X102MGkuvBIZ6usAaMutlDLdVaL0,6185
|
8
|
+
uagents_core/logger.py,sha256=5XLs3-XpKDeoSwtAE5pEM9h6x3pUPNbb0T0J7KvFmG0,877
|
9
|
+
uagents_core/models.py,sha256=fxsFjRochkJUdgPltT1HWgBl-9K-HVQWl8sSMVgeJFY,1066
|
10
|
+
uagents_core/protocol.py,sha256=T9jasOkltne33E16Y7VrqcB2moWVsv-Qh4XLZotyz8g,5428
|
11
|
+
uagents_core/registration.py,sha256=h7ha58H7XbLQ__qOHMKVnHShzMlWfd2xrK9fRdgfb9w,2953
|
12
|
+
uagents_core/types.py,sha256=_W3EN1wEIRFxuhhBxyZxQH_dA_3AtoPPReIzrgcTUHc,1167
|
13
|
+
uagents_core/utils/__init__.py,sha256=v0MaxDYCTtQlwbblEHCfLtbeTnA2hCmKKJk7mlcE20U,135
|
14
|
+
uagents_core/utils/messages.py,sha256=O4Fk8KULi523ruynEw1ZxAxFKi4ex816R4a_Q1E24O8,5056
|
15
|
+
uagents_core/utils/registration.py,sha256=ny_2Svz1RLgMcH0WgBlzWKhZnhN25Yuni2eHFksoMjU,9039
|
16
|
+
uagents_core/utils/resolver.py,sha256=X18oe-WPU_6pfTc6x_Oa69kZQYCMidkaSeCs68Poaik,2169
|
17
|
+
uagents_core-0.2.0.dist-info/METADATA,sha256=OAsIUaGEiH9rehxRlGedKly53jQk1-GjEqA7Q-cwud0,1009
|
18
|
+
uagents_core-0.2.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
19
|
+
uagents_core-0.2.0.dist-info/RECORD,,
|
uagents_core/communication.py
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
import random
|
2
|
-
from typing import Any, List, Optional, Tuple
|
3
|
-
|
4
|
-
from uagents_core.config import (
|
5
|
-
AGENT_ADDRESS_LENGTH,
|
6
|
-
AGENT_PREFIX,
|
7
|
-
)
|
8
|
-
from uagents_core.crypto import is_user_address
|
9
|
-
|
10
|
-
|
11
|
-
def weighted_random_sample(
|
12
|
-
items: List[Any], weights: Optional[List[float]] = None, k: int = 1, rng=random
|
13
|
-
) -> List[Any]:
|
14
|
-
"""
|
15
|
-
Weighted random sample from a list of items without replacement.
|
16
|
-
|
17
|
-
Ref: Efraimidis, Pavlos S. "Weighted random sampling over data streams."
|
18
|
-
|
19
|
-
Args:
|
20
|
-
items (List[Any]): The list of items to sample from.
|
21
|
-
weights (Optional[List[float]]): The optional list of weights for each item.
|
22
|
-
k (int): The number of items to sample.
|
23
|
-
rng (random): The random number generator.
|
24
|
-
|
25
|
-
Returns:
|
26
|
-
List[Any]: The sampled items.
|
27
|
-
"""
|
28
|
-
if weights is None:
|
29
|
-
return rng.sample(items, k=k)
|
30
|
-
values = [rng.random() ** (1 / w) for w in weights]
|
31
|
-
order = sorted(range(len(items)), key=lambda i: values[i])
|
32
|
-
return [items[i] for i in order[-k:]]
|
33
|
-
|
34
|
-
|
35
|
-
def is_valid_address(address: str) -> bool:
|
36
|
-
"""
|
37
|
-
Check if the given string is a valid address.
|
38
|
-
|
39
|
-
Args:
|
40
|
-
address (str): The address to be checked.
|
41
|
-
|
42
|
-
Returns:
|
43
|
-
bool: True if the address is valid; False otherwise.
|
44
|
-
"""
|
45
|
-
return is_user_address(address) or (
|
46
|
-
len(address) == AGENT_ADDRESS_LENGTH and address.startswith(AGENT_PREFIX)
|
47
|
-
)
|
48
|
-
|
49
|
-
|
50
|
-
def parse_identifier(identifier: str) -> Tuple[str, str, str]:
|
51
|
-
"""
|
52
|
-
Parse an agent identifier string into prefix, name, and address.
|
53
|
-
|
54
|
-
Args:
|
55
|
-
identifier (str): The identifier string to be parsed.
|
56
|
-
|
57
|
-
Returns:
|
58
|
-
Tuple[str, str, str]: A Tuple containing the prefix, name, and address as strings.
|
59
|
-
"""
|
60
|
-
|
61
|
-
prefix = ""
|
62
|
-
name = ""
|
63
|
-
address = ""
|
64
|
-
|
65
|
-
if "://" in identifier:
|
66
|
-
prefix, identifier = identifier.split("://", 1)
|
67
|
-
|
68
|
-
if "/" in identifier:
|
69
|
-
name, identifier = identifier.split("/", 1)
|
70
|
-
|
71
|
-
if is_valid_address(identifier):
|
72
|
-
address = identifier
|
73
|
-
else:
|
74
|
-
name = identifier
|
75
|
-
|
76
|
-
return prefix, name, address
|