1414 "LLMInternalError" ,
1515]
1616
17+ # Mapping from API error codes to exception classes
18+ ERROR_CODE_EXCEPTIONS = {
19+ "FunctionalRequirementTooComplex" : plain2code_exceptions .FunctionalRequirementTooComplex ,
20+ "ConflictingRequirements" : plain2code_exceptions .ConflictingRequirements ,
21+ "CreditBalanceTooLow" : plain2code_exceptions .CreditBalanceTooLow ,
22+ "LLMInternalError" : plain2code_exceptions .LLMInternalError ,
23+ "MissingResource" : plain2code_exceptions .MissingResource ,
24+ "PlainSyntaxError" : plain2code_exceptions .PlainSyntaxError ,
25+ "InternalServerError" : plain2code_exceptions .InternalServerError ,
26+ }
27+
1728
1829class CodeplainAPI :
1930
@@ -33,13 +44,31 @@ def _extend_payload_with_run_state(self, payload: dict, run_state: RunState):
3344 run_state .increment_call_count ()
3445 payload ["render_state" ] = run_state .to_dict ()
3546
36- def post_request (self , endpoint_url , headers , payload , run_state : Optional [RunState ]): # noqa: C901
47+ def _raise_for_error_code (self , response_json ):
48+ """Raise appropriate exception based on error code in response."""
49+ error_code = response_json .get ("error_code" )
50+ if error_code not in ERROR_CODE_EXCEPTIONS :
51+ return
52+
53+ exception_class = ERROR_CODE_EXCEPTIONS [error_code ]
54+ message = response_json .get ("message" , "" )
55+
56+ # FunctionalRequirementTooComplex has an extra parameter
57+ if error_code == "FunctionalRequirementTooComplex" :
58+ raise exception_class (message , response_json .get ("proposed_breakdown" ))
59+
60+ raise exception_class (message )
61+
62+ def post_request (
63+ self , endpoint_url , headers , payload , run_state : Optional [RunState ], num_retries : int = MAX_RETRIES
64+ ):
3765 if run_state is not None :
3866 self ._extend_payload_with_run_state (payload , run_state )
3967
4068 retry_delay = RETRY_DELAY
4169 response_json = None
42- for attempt in range (MAX_RETRIES + 1 ):
70+
71+ for attempt in range (num_retries + 1 ):
4372 try :
4473 response = requests .post (endpoint_url , headers = headers , json = payload )
4574
@@ -50,28 +79,7 @@ def post_request(self, endpoint_url, headers, payload, run_state: Optional[RunSt
5079 raise
5180
5281 if response .status_code == requests .codes .bad_request and "error_code" in response_json :
53- if response_json ["error_code" ] == "FunctionalRequirementTooComplex" :
54- raise plain2code_exceptions .FunctionalRequirementTooComplex (
55- response_json ["message" ], response_json .get ("proposed_breakdown" )
56- )
57-
58- if response_json ["error_code" ] == "ConflictingRequirements" :
59- raise plain2code_exceptions .ConflictingRequirements (response_json ["message" ])
60-
61- if response_json ["error_code" ] == "CreditBalanceTooLow" :
62- raise plain2code_exceptions .CreditBalanceTooLow (response_json ["message" ])
63-
64- if response_json ["error_code" ] == "LLMInternalError" :
65- raise plain2code_exceptions .LLMInternalError (response_json ["message" ])
66-
67- if response_json ["error_code" ] == "MissingResource" :
68- raise plain2code_exceptions .MissingResource (response_json ["message" ])
69-
70- if response_json ["error_code" ] == "PlainSyntaxError" :
71- raise plain2code_exceptions .PlainSyntaxError (response_json ["message" ])
72-
73- if response_json ["error_code" ] == "InternalServerError" :
74- raise plain2code_exceptions .InternalServerError (response_json ["message" ])
82+ self ._raise_for_error_code (response_json )
7583
7684 response .raise_for_status ()
7785 return response_json
@@ -81,16 +89,24 @@ def post_request(self, endpoint_url, headers, payload, run_state: Optional[RunSt
8189 if response_json ["error_code" ] not in RETRY_ERROR_CODES :
8290 raise e
8391
84- if attempt < MAX_RETRIES :
85- self .console .info (f"Error on attempt { attempt + 1 } /{ MAX_RETRIES + 1 } : { e } " )
92+ if attempt < num_retries :
93+ self .console .info (f"Error on attempt { attempt + 1 } /{ num_retries + 1 } : { e } " )
8694 self .console .info (f"Retrying in { retry_delay } seconds..." )
8795 time .sleep (retry_delay )
88- # Exponential backoff
89- retry_delay *= 2
96+ retry_delay *= 2 # Exponential backoff
9097 else :
91- self .console .error (f"Max retries ({ MAX_RETRIES } ) exceeded. Last error: { e } " )
98+ self .console .error (f"Max retries ({ num_retries } ) exceeded. Last error: { e } " )
9299 raise e
93100
101+ def connection_check (self , client_version ):
102+ endpoint_url = f"{ self .api_url } /connection_check"
103+ headers = {"Content-Type" : "application/json" }
104+ payload = {
105+ "api_key" : self .api_key ,
106+ "client_version" : client_version ,
107+ }
108+ return self .post_request (endpoint_url , headers , payload , None , num_retries = 0 )
109+
94110 def render_functional_requirement (
95111 self ,
96112 frid : str ,
0 commit comments