11import os
2+ import time
3+
4+
5+ class APIUnavailable (Exception ):
6+ """Raised when the API cannot be reached or returns a non-JSON response."""
27
38
49class AgentWatchClient :
@@ -10,28 +15,45 @@ def __init__(self, base_url: str | None = None, api_key: str | None = None, clie
1015 if client is None :
1116 import httpx
1217
13- client = httpx .Client (base_url = self .base_url , timeout = 30.0 )
18+ client = httpx .Client (base_url = self .base_url , timeout = 30.0 , follow_redirects = True )
1419 self ._client = client
1520
1621 def _headers (self ) -> dict :
1722 return {"X-API-Key" : self .api_key } if self .api_key else {}
1823
24+ def _get_json (self , path : str , params : dict | None = None , * , attempts : int = 3 ):
25+ last : Exception | None = None
26+ for i in range (attempts ):
27+ try :
28+ resp = self ._client .get (path , params = params or {})
29+ resp .raise_for_status ()
30+ return resp .json ()
31+ except Exception as exc : # network error, non-2xx, or non-JSON body
32+ last = exc
33+ if i < attempts - 1 :
34+ time .sleep (1.5 * (i + 1 ))
35+ raise APIUnavailable (str (last )) from last
36+
1937 def incidents (self , ** filters ) -> dict :
2038 params = {k : v for k , v in filters .items () if v is not None }
21- return self ._client . get ("/incidents" , params = params ). json ( )
39+ return self ._get_json ("/incidents" , params )
2240
2341 def incident (self , incident_id : int ) -> dict :
24- return self ._client . get (f"/incidents/{ incident_id } " ). json ( )
42+ return self ._get_json (f"/incidents/{ incident_id } " )
2543
2644 def stats (self ) -> dict :
27- return self ._client . get ("/stats" ). json ( )
45+ return self ._get_json ("/stats" )
2846
2947 def review (
3048 self , incident_id : int , * , reviewer : str , decision : str , notes : str | None = None
3149 ) -> dict :
32- resp = self ._client .post (
33- f"/incidents/{ incident_id } /review" ,
34- json = {"reviewer" : reviewer , "decision" : decision , "notes" : notes },
35- headers = self ._headers (),
36- )
37- return resp .json ()
50+ try :
51+ resp = self ._client .post (
52+ f"/incidents/{ incident_id } /review" ,
53+ json = {"reviewer" : reviewer , "decision" : decision , "notes" : notes },
54+ headers = self ._headers (),
55+ )
56+ resp .raise_for_status ()
57+ return resp .json ()
58+ except Exception as exc :
59+ raise APIUnavailable (str (exc )) from exc
0 commit comments