6969# Supervisor is local to the app network, so connection acquisition should
7070# remain short even when an app operation needs a multi-minute response budget.
7171_SUPERVISOR_ACQUIRE_TIMEOUT = 10.0
72+ _SUPERVISOR_AVAILABILITY_SUGGESTION = (
73+ "Check Home Assistant connection and Supervisor availability"
74+ )
75+ _SUPERVISOR_RESPONSE_TRUNCATION_SUFFIX = (
76+ f"\n [Supervisor response truncated to { _MAX_RESPONSE_SIZE // 1024 } KiB]"
77+ )
7278
7379# Hard safety cap on WebSocket messages collected per call. `message_limit`
7480# can lower this but never raise it.
@@ -310,6 +316,15 @@ def _supervisor_invalid_response(
310316 return _supervisor_rest_failure (response , error )
311317
312318
319+ def _bounded_supervisor_response_text (response : httpx .Response ) -> str :
320+ """Return a model-safe Supervisor response body with visible truncation."""
321+ body = response .text .strip ()
322+ if len (body ) <= _MAX_RESPONSE_SIZE :
323+ return body
324+ prefix_size = _MAX_RESPONSE_SIZE - len (_SUPERVISOR_RESPONSE_TRUNCATION_SUFFIX )
325+ return body [:prefix_size ] + _SUPERVISOR_RESPONSE_TRUNCATION_SUFFIX
326+
327+
313328def _normalize_supervisor_rest_response (
314329 response : httpx .Response ,
315330 endpoint : str ,
@@ -321,7 +336,7 @@ def _normalize_supervisor_rest_response(
321336 300 <= response .status_code < 400 or response .status_code >= 500
322337 )
323338 if write_outcome_unknown :
324- response_body = response . text . strip ()[: _MAX_RESPONSE_SIZE ]
339+ response_body = _bounded_supervisor_response_text ( response )
325340 _raise_supervisor_write_outcome_unknown (
326341 ErrorCode .SERVICE_CALL_FAILED ,
327342 f"Supervisor API { verb } { endpoint } returned HTTP "
@@ -335,7 +350,7 @@ def _normalize_supervisor_rest_response(
335350 try :
336351 payload = response .json ()
337352 except ValueError :
338- body = response . text . strip ( )
353+ body = _bounded_supervisor_response_text ( response )
339354 error_message = (
340355 body or f"Supervisor returned invalid JSON (HTTP { response .status_code } )"
341356 )
@@ -750,21 +765,24 @@ async def _supervisor_api_call(
750765 raise
751766 except Exception as e :
752767 logger .error (f"Error calling Supervisor API { endpoint } : { e } " )
753- suggestions = None
754- if isinstance (e , HomeAssistantAPIError ) and e .status_code == 404 :
755- suggestions = [
756- "Check Home Assistant connection and Supervisor availability"
757- ]
758- exception_to_structured_error (
768+ error_response = exception_to_structured_error (
759769 e ,
760770 context = {
761771 "endpoint" : endpoint ,
762772 "operation" : f"Supervisor API { endpoint } " ,
763773 "timeout_seconds" : wait_timeout ,
764774 },
765- suggestions = suggestions ,
775+ raise_error = False ,
766776 )
767- return None # unreachable: exception_to_structured_error always raises
777+ error_details = error_response .get ("error" )
778+ if (
779+ isinstance (error_details , dict )
780+ and error_details .get ("code" ) == ErrorCode .RESOURCE_NOT_FOUND .value
781+ ):
782+ error_details ["suggestion" ] = _SUPERVISOR_AVAILABILITY_SUGGESTION
783+ error_details ["suggestions" ] = [_SUPERVISOR_AVAILABILITY_SUGGESTION ]
784+ raise_tool_error (error_response )
785+ return None # unreachable: raise_tool_error always raises
768786
769787
770788def _addon_connection_failure_suggestions (
0 commit comments