@@ -825,9 +825,7 @@ class ResilientLLM {
825825
826826 console . log ( "Response Headers:" , response ?. headers ) ;
827827
828- const data = await response ?. json ( ) as Record < string , unknown > ;
829-
830- const result : HttpResult = { data, statusCode : response ?. status } ;
828+ const result = await ResilientLLM . _readProviderJsonResponse ( response ) ;
831829
832830 const httpDurationMs = Date . now ( ) - httpStartTime ;
833831 console . log ( `Request to ${ apiUrl } completed in ${ httpDurationMs } ms` ) ;
@@ -853,6 +851,80 @@ class ResilientLLM {
853851 }
854852 }
855853
854+ /**
855+ * Reads a provider response as JSON when possible, otherwise returns a synthetic JSON error payload.
856+ */
857+ static async _readProviderJsonResponse ( response : Response ) : Promise < HttpResult > {
858+ const statusCode = response ?. status ?? 0 ;
859+ const contentType = response ?. headers ?. get ?.( 'content-type' ) || '' ;
860+ const normalizedContentType = contentType . toLowerCase ( ) ;
861+ const isJson = normalizedContentType . includes ( 'application/json' ) || normalizedContentType . includes ( '+json' ) ;
862+ const responseLike = response as Response & {
863+ text ?: ( ) => Promise < string > ;
864+ json ?: ( ) => Promise < unknown > ;
865+ } ;
866+
867+ // Prefer text() when available to keep a single, controlled body parse path.
868+ if ( typeof responseLike . text === 'function' ) {
869+ const raw = await responseLike . text ( ) . catch ( ( ) => '' ) ;
870+ const snippet = ( raw || '' ) . slice ( 0 , 2000 ) ;
871+
872+ if ( isJson ) {
873+ try {
874+ const parsed = raw ? ( JSON . parse ( raw ) as Record < string , unknown > ) : ( { } as Record < string , unknown > ) ;
875+ return { data : parsed , statusCode } ;
876+ } catch {
877+ return {
878+ statusCode,
879+ data : {
880+ error : {
881+ message : `Invalid JSON from provider (HTTP ${ statusCode } ). ${ snippet ? `Body: ${ snippet } ` : 'Empty body.' } ` ,
882+ } ,
883+ } ,
884+ } ;
885+ }
886+ }
887+
888+ return {
889+ statusCode,
890+ data : {
891+ error : {
892+ message : `Expected JSON from provider but received "${ contentType || 'unknown' } " (HTTP ${ statusCode } ). ${ snippet ? `Body: ${ snippet } ` : 'Empty body.' } ` ,
893+ } ,
894+ } ,
895+ } ;
896+ }
897+
898+ // Compatibility fallback for partial/mock responses that only expose json().
899+ if ( typeof responseLike . json === 'function' ) {
900+ try {
901+ const parsed = await responseLike . json ( ) ;
902+ return {
903+ statusCode,
904+ data : ( parsed ?? { } ) as Record < string , unknown > ,
905+ } ;
906+ } catch {
907+ return {
908+ statusCode,
909+ data : {
910+ error : {
911+ message : `Invalid JSON from provider (HTTP ${ statusCode } ). Empty body.` ,
912+ } ,
913+ } ,
914+ } ;
915+ }
916+ }
917+
918+ return {
919+ statusCode,
920+ data : {
921+ error : {
922+ message : `Expected JSON from provider but received "${ contentType || 'unknown' } " (HTTP ${ statusCode } ). Empty body.` ,
923+ } ,
924+ } ,
925+ } ;
926+ }
927+
856928 static _captureHttpMetadata (
857929 metadata : OperationMetadata ,
858930 apiUrl : string ,
0 commit comments