1010if TYPE_CHECKING :
1111 from agentscore .types import (
1212 AssessResponse ,
13+ CredentialCreateResponse ,
14+ CredentialListResponse ,
1315 DecisionPolicy ,
1416 ReputationResponse ,
17+ SessionCreateResponse ,
18+ SessionPollResponse ,
1519 )
1620
1721
@@ -58,6 +62,13 @@ def _get_async_client(self) -> httpx.AsyncClient:
5862 return self ._async_client
5963
6064 def _handle_response (self , response : httpx .Response ) -> dict :
65+ if response .status_code == 429 :
66+ retry_after = response .headers .get ("retry-after" , "1" )
67+ raise AgentScoreError (
68+ code = "rate_limited" ,
69+ message = f"Rate limit exceeded. Retry after { retry_after } s" ,
70+ status_code = 429 ,
71+ )
6172 if response .status_code >= 400 :
6273 try :
6374 body = response .json ()
@@ -95,13 +106,18 @@ def get_reputation(self, address: str, chain: str | None = None) -> ReputationRe
95106
96107 def assess (
97108 self ,
98- address : str ,
109+ address : str | None = None ,
99110 chain : str | None = None ,
100111 refresh : bool = False ,
101112 policy : DecisionPolicy | None = None ,
113+ operator_token : str | None = None ,
102114 ) -> AssessResponse :
103- """Assess a wallet (paid, writes score on-the-fly)."""
104- body : dict [str , Any ] = {"address" : address }
115+ """Assess a wallet or operator (paid, writes score on-the-fly)."""
116+ body : dict [str , Any ] = {}
117+ if address :
118+ body ["address" ] = address
119+ if operator_token :
120+ body ["operator_token" ] = operator_token
105121 if chain :
106122 body ["chain" ] = chain
107123 if refresh :
@@ -112,6 +128,57 @@ def assess(
112128 response = client .post ("/v1/assess" , json = body )
113129 return self ._handle_response (response )
114130
131+ def create_session (
132+ self ,
133+ context : str | None = None ,
134+ product_name : str | None = None ,
135+ ) -> SessionCreateResponse :
136+ """Create an assessment session for deferred scoring."""
137+ body : dict [str , Any ] = {}
138+ if context is not None :
139+ body ["context" ] = context
140+ if product_name is not None :
141+ body ["product_name" ] = product_name
142+ client = self ._get_sync_client ()
143+ response = client .post ("/v1/sessions" , json = body )
144+ return self ._handle_response (response )
145+
146+ def poll_session (self , session_id : str , poll_secret : str ) -> SessionPollResponse :
147+ """Poll a session for its current status and result."""
148+ client = self ._get_sync_client ()
149+ response = client .get (
150+ f"/v1/sessions/{ session_id } " ,
151+ headers = {"X-Poll-Secret" : poll_secret },
152+ )
153+ return self ._handle_response (response )
154+
155+ def create_credential (
156+ self ,
157+ label : str | None = None ,
158+ ttl_days : int | None = None ,
159+ ) -> CredentialCreateResponse :
160+ """Create a new API credential."""
161+ body : dict [str , Any ] = {}
162+ if label is not None :
163+ body ["label" ] = label
164+ if ttl_days is not None :
165+ body ["ttl_days" ] = ttl_days
166+ client = self ._get_sync_client ()
167+ response = client .post ("/v1/credentials" , json = body )
168+ return self ._handle_response (response )
169+
170+ def list_credentials (self ) -> CredentialListResponse :
171+ """List all API credentials."""
172+ client = self ._get_sync_client ()
173+ response = client .get ("/v1/credentials" )
174+ return self ._handle_response (response )
175+
176+ def revoke_credential (self , id : str ) -> dict :
177+ """Revoke an API credential by ID."""
178+ client = self ._get_sync_client ()
179+ response = client .delete (f"/v1/credentials/{ id } " )
180+ return self ._handle_response (response )
181+
115182 # --- Async methods ---
116183
117184 async def aget_reputation (self , address : str , chain : str | None = None ) -> ReputationResponse :
@@ -125,13 +192,18 @@ async def aget_reputation(self, address: str, chain: str | None = None) -> Reput
125192
126193 async def aassess (
127194 self ,
128- address : str ,
195+ address : str | None = None ,
129196 chain : str | None = None ,
130197 refresh : bool = False ,
131198 policy : DecisionPolicy | None = None ,
199+ operator_token : str | None = None ,
132200 ) -> AssessResponse :
133- """Assess a wallet (paid, writes score on-the-fly)."""
134- body : dict [str , Any ] = {"address" : address }
201+ """Assess a wallet or operator (paid, writes score on-the-fly)."""
202+ body : dict [str , Any ] = {}
203+ if address :
204+ body ["address" ] = address
205+ if operator_token :
206+ body ["operator_token" ] = operator_token
135207 if chain :
136208 body ["chain" ] = chain
137209 if refresh :
@@ -142,6 +214,57 @@ async def aassess(
142214 response = await client .post ("/v1/assess" , json = body )
143215 return self ._handle_response (response )
144216
217+ async def acreate_session (
218+ self ,
219+ context : str | None = None ,
220+ product_name : str | None = None ,
221+ ) -> SessionCreateResponse :
222+ """Create an assessment session for deferred scoring."""
223+ body : dict [str , Any ] = {}
224+ if context is not None :
225+ body ["context" ] = context
226+ if product_name is not None :
227+ body ["product_name" ] = product_name
228+ client = self ._get_async_client ()
229+ response = await client .post ("/v1/sessions" , json = body )
230+ return self ._handle_response (response )
231+
232+ async def apoll_session (self , session_id : str , poll_secret : str ) -> SessionPollResponse :
233+ """Poll a session for its current status and result."""
234+ client = self ._get_async_client ()
235+ response = await client .get (
236+ f"/v1/sessions/{ session_id } " ,
237+ headers = {"X-Poll-Secret" : poll_secret },
238+ )
239+ return self ._handle_response (response )
240+
241+ async def acreate_credential (
242+ self ,
243+ label : str | None = None ,
244+ ttl_days : int | None = None ,
245+ ) -> CredentialCreateResponse :
246+ """Create a new API credential."""
247+ body : dict [str , Any ] = {}
248+ if label is not None :
249+ body ["label" ] = label
250+ if ttl_days is not None :
251+ body ["ttl_days" ] = ttl_days
252+ client = self ._get_async_client ()
253+ response = await client .post ("/v1/credentials" , json = body )
254+ return self ._handle_response (response )
255+
256+ async def alist_credentials (self ) -> CredentialListResponse :
257+ """List all API credentials."""
258+ client = self ._get_async_client ()
259+ response = await client .get ("/v1/credentials" )
260+ return self ._handle_response (response )
261+
262+ async def arevoke_credential (self , id : str ) -> dict :
263+ """Revoke an API credential by ID."""
264+ client = self ._get_async_client ()
265+ response = await client .delete (f"/v1/credentials/{ id } " )
266+ return self ._handle_response (response )
267+
145268 def close (self ):
146269 if self ._sync_client :
147270 self ._sync_client .close ()
0 commit comments