uagents-core 0.2.3__py3-none-any.whl → 0.3.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 CHANGED
@@ -6,6 +6,7 @@ DEFAULT_REGISTRATION_PATH = "/v1/agents"
6
6
  DEFAULT_CHALLENGE_PATH = "/v1/auth/challenge"
7
7
  DEFAULT_MAILBOX_PATH = "/v1/submit"
8
8
  DEFAULT_PROXY_PATH = "/v1/proxy/submit"
9
+ DEFAULT_STORAGE_PATH = "/v1/storage"
9
10
 
10
11
  DEFAULT_MAX_ENDPOINTS = 10
11
12
 
@@ -30,3 +31,7 @@ class AgentverseConfig(BaseModel):
30
31
  @property
31
32
  def proxy_endpoint(self) -> str:
32
33
  return f"{self.url}{DEFAULT_PROXY_PATH}"
34
+
35
+ @property
36
+ def storage_endpoint(self) -> str:
37
+ return f"{self.url}{DEFAULT_STORAGE_PATH}"
@@ -0,0 +1,135 @@
1
+ import base64
2
+ import struct
3
+ from datetime import datetime
4
+ from secrets import token_bytes
5
+ from typing import Optional
6
+
7
+ import requests
8
+
9
+ from uagents_core.config import AgentverseConfig
10
+ from uagents_core.identity import Identity
11
+
12
+
13
+ def compute_attestation(
14
+ identity: Identity, validity_start: datetime, validity_secs: int, nonce: bytes
15
+ ) -> str:
16
+ """
17
+ Compute a valid agent attestation token for authentication.
18
+ """
19
+ assert len(nonce) == 32, "Nonce is of invalid length"
20
+
21
+ valid_from = int(validity_start.timestamp())
22
+ valid_to = valid_from + validity_secs
23
+
24
+ public_key = bytes.fromhex(identity.pub_key)
25
+
26
+ payload = public_key + struct.pack(">QQ", valid_from, valid_to) + nonce
27
+ assert len(payload) == 81, "attestation payload is incorrect"
28
+
29
+ signature = identity.sign(payload)
30
+ attestation = f"attr:{base64.b64encode(payload).decode()}:{signature}"
31
+ return attestation
32
+
33
+
34
+ class ExternalStorage:
35
+ def __init__(
36
+ self,
37
+ identity: Optional[Identity] = None,
38
+ storage_url: Optional[str] = None,
39
+ api_token: Optional[str] = None,
40
+ ):
41
+ self.identity = identity
42
+ self.api_token = api_token
43
+ self.storage_url = storage_url or AgentverseConfig().storage_endpoint
44
+
45
+ def _make_attestation(self) -> str:
46
+ nonce = token_bytes(32)
47
+ now = datetime.now()
48
+ return compute_attestation(self.identity, now, 3600, nonce)
49
+
50
+ def _get_auth_header(self) -> dict:
51
+ if self.api_token:
52
+ return {"Authorization": f"Bearer {self.api_token}"}
53
+ elif self.identity:
54
+ return {"Authorization": f"Agent {self._make_attestation()}"}
55
+ else:
56
+ raise RuntimeError("No identity or API token available for authentication")
57
+
58
+ def upload(
59
+ self, asset_id: str, asset_content: str, mime_type: str = "text/plain"
60
+ ) -> dict:
61
+ url = f"{self.storage_url}/assets/{asset_id}/contents/"
62
+ headers = self._get_auth_header()
63
+ headers["Content-Type"] = "application/json"
64
+ payload = {
65
+ "contents": base64.b64encode(asset_content.encode()).decode(),
66
+ "mime_type": mime_type,
67
+ }
68
+ response = requests.put(url, json=payload, headers=headers)
69
+ if response.status_code != 200:
70
+ raise RuntimeError(
71
+ f"Upload failed: {response.status_code}, {response.text}"
72
+ )
73
+
74
+ return response.json()
75
+
76
+ def download(self, asset_id: str) -> dict:
77
+ url = f"{self.storage_url}/assets/{asset_id}/contents/"
78
+ headers = self._get_auth_header()
79
+
80
+ response = requests.get(url, headers=headers)
81
+ if response.status_code != 200:
82
+ raise RuntimeError(
83
+ f"Download failed: {response.status_code}, {response.text}"
84
+ )
85
+
86
+ return response.json()
87
+
88
+ def create_asset(
89
+ self,
90
+ name: str,
91
+ content: str,
92
+ mime_type: str = "text/plain",
93
+ lifetime_hours: int = 24,
94
+ ) -> str:
95
+ if not self.api_token:
96
+ raise RuntimeError("API token required to create assets")
97
+ url = f"{self.storage_url}/assets/"
98
+ headers = self._get_auth_header()
99
+ headers["Content-Type"] = "application/json"
100
+ payload = {
101
+ "name": name,
102
+ "mime_type": mime_type,
103
+ "contents": base64.b64encode(content.encode()).decode(),
104
+ "lifetime_hours": lifetime_hours,
105
+ }
106
+
107
+ response = requests.post(url, json=payload, headers=headers)
108
+ if response.status_code != 201:
109
+ raise RuntimeError(
110
+ f"Asset creation failed: {response.status_code}, {response.text}"
111
+ )
112
+
113
+ return response.json()["asset_id"]
114
+
115
+ def set_permissions(
116
+ self, asset_id: str, agent_address: str, read: bool = True, write: bool = True
117
+ ):
118
+ if not self.api_token:
119
+ raise RuntimeError("API token required to set permissions")
120
+ url = f"{self.storage_url}/assets/{asset_id}/permissions/"
121
+ headers = self._get_auth_header()
122
+ headers["Content-Type"] = "application/json"
123
+ payload = {
124
+ "agent_address": agent_address,
125
+ "read": read,
126
+ "write": write,
127
+ }
128
+
129
+ response = requests.put(url, json=payload, headers=headers)
130
+ if response.status_code != 200:
131
+ raise RuntimeError(
132
+ f"Set permissions failed: {response.status_code}, {response.text}"
133
+ )
134
+
135
+ return response.json()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: uagents-core
3
- Version: 0.2.3
3
+ Version: 0.3.0
4
4
  Summary: Core components for agent based systems
5
5
  License: Apache 2.0
6
6
  Author: Ed FitzGerald
@@ -1,5 +1,5 @@
1
1
  uagents_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- uagents_core/config.py,sha256=mvCXtvt_efDbmoTcw0JNHymWZGOtXxIYXlrooWfbY1Q,798
2
+ uagents_core/config.py,sha256=Cz2c2qhS_0uqUPxG7mWiqQSXWI_rPrfC7VoTSwBkdWk,940
3
3
  uagents_core/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  uagents_core/contrib/protocols/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  uagents_core/contrib/protocols/chat/__init__.py,sha256=EAt2uQeaZtrSEdt2SiFyqFcC4nxKtyoJRaHhjKtwngw,3032
@@ -11,11 +11,12 @@ uagents_core/logger.py,sha256=5XLs3-XpKDeoSwtAE5pEM9h6x3pUPNbb0T0J7KvFmG0,877
11
11
  uagents_core/models.py,sha256=fxsFjRochkJUdgPltT1HWgBl-9K-HVQWl8sSMVgeJFY,1066
12
12
  uagents_core/protocol.py,sha256=T9jasOkltne33E16Y7VrqcB2moWVsv-Qh4XLZotyz8g,5428
13
13
  uagents_core/registration.py,sha256=h7ha58H7XbLQ__qOHMKVnHShzMlWfd2xrK9fRdgfb9w,2953
14
+ uagents_core/storage.py,sha256=A7s2jJhdbDI0aNKAcjJpL5oxcYrb2FnHhXGwlAt3RY4,4506
14
15
  uagents_core/types.py,sha256=_W3EN1wEIRFxuhhBxyZxQH_dA_3AtoPPReIzrgcTUHc,1167
15
16
  uagents_core/utils/__init__.py,sha256=v0MaxDYCTtQlwbblEHCfLtbeTnA2hCmKKJk7mlcE20U,135
16
17
  uagents_core/utils/messages.py,sha256=5o3ahVaeGwzWMAxDs0fl2pC1duDq2VS_-czoVtZpkOc,5066
17
18
  uagents_core/utils/registration.py,sha256=HaA0J2yisx0bwVs1LbpJ4UP3-maeeAf37yziI-U07l8,9067
18
19
  uagents_core/utils/resolver.py,sha256=X18oe-WPU_6pfTc6x_Oa69kZQYCMidkaSeCs68Poaik,2169
19
- uagents_core-0.2.3.dist-info/METADATA,sha256=9_LsBarAzyOA-ttbyu_4Y5h8kLaVUTZiB3EyjkKKK8o,1009
20
- uagents_core-0.2.3.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
21
- uagents_core-0.2.3.dist-info/RECORD,,
20
+ uagents_core-0.3.0.dist-info/METADATA,sha256=SpfzcsoEMP44pjC4tRmjq0kx8UHr-KPSZ4kZGG6jp8A,1009
21
+ uagents_core-0.3.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
22
+ uagents_core-0.3.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.2
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any