@@ -137,7 +137,9 @@ function extractJson(raw: string) {
137137 // Truncated JSON: the closing brace(s) are missing. Append them so jsonrepair
138138 // has a structurally complete (though incomplete-content) object to work with.
139139 const partial = raw . slice ( firstBrace ) . trim ( ) ;
140- const closing = '}' . repeat ( Math . max ( 1 , stack ) ) ;
140+ let closing = '' ;
141+ if ( inString ) closing += '"' ;
142+ closing += '}' . repeat ( Math . max ( 1 , stack ) ) ;
141143 return `${ partial } ${ closing } ` ;
142144 }
143145
@@ -157,36 +159,37 @@ function coerceReviewNumber(value: unknown) {
157159 return undefined ;
158160}
159161
160- function normalizeFinding ( finding : any ) {
162+ function normalizeFinding ( finding : unknown ) {
161163 if ( ! finding || typeof finding !== 'object' ) return null ;
162- if ( isPlaceholderString ( finding . title ) || isPlaceholderString ( finding . body ) ) return null ;
164+ const f = finding as Record < string , unknown > ;
165+ if ( isPlaceholderString ( f . title ) || isPlaceholderString ( f . body ) ) return null ;
163166
164- const location = finding . code_location && typeof finding . code_location === 'object' ? finding . code_location : { } ;
167+ const location = f . code_location && typeof f . code_location === 'object' ? ( f . code_location as Record < string , unknown > ) : { } ;
165168 const line = coerceReviewNumber ( location . line ) ;
166- const start = coerceReviewNumber ( location . line_range ?. start ) ;
167- const end = coerceReviewNumber ( location . line_range ?. end ) ;
168- const priority = coerceReviewNumber ( finding . priority ) ;
169+ const start = coerceReviewNumber ( location . line_range && typeof location . line_range === 'object' ? ( location . line_range as Record < string , unknown > ) . start : undefined ) ;
170+ const end = coerceReviewNumber ( location . line_range && typeof location . line_range === 'object' ? ( location . line_range as Record < string , unknown > ) . end : undefined ) ;
171+ const priority = coerceReviewNumber ( f . priority ) ;
169172
170173 const codeLocation : Record < string , unknown > = {
171- absolute_file_path : location . absolute_file_path || finding . path || '' ,
174+ absolute_file_path : location . absolute_file_path || f . path || '' ,
172175 } ;
173176 if ( line !== undefined ) {
174- codeLocation . line = Math . trunc ( line ) ;
177+ codeLocation . line = Math . trunc ( line as number ) ;
175178 }
176179 if ( start !== undefined || end !== undefined ) {
177180 codeLocation . line_range = {
178- start : Math . trunc ( start ?? end ! ) ,
179- end : Math . trunc ( end ?? start ! ) ,
181+ start : Math . trunc ( ( start as number ) ?? ( end as number ) ! ) ,
182+ end : Math . trunc ( ( end as number ) ?? ( start as number ) ! ) ,
180183 } ;
181184 }
182185
183186 return {
184- ...finding ,
185- title : finding . title || 'Code finding' ,
186- priority : priority === undefined ? undefined : Math . max ( 0 , Math . min ( 3 , Math . trunc ( priority ) ) ) ,
187+ ...f ,
188+ title : f . title || 'Code finding' ,
189+ priority : priority === undefined ? undefined : Math . max ( 0 , Math . min ( 3 , Math . trunc ( priority as number ) ) ) ,
187190 code_location : codeLocation ,
188- confidence_score : typeof finding . confidence_score === 'number'
189- ? Math . max ( 0 , Math . min ( 1 , finding . confidence_score > 1 ? finding . confidence_score / 10 : finding . confidence_score ) )
191+ confidence_score : typeof f . confidence_score === 'number'
192+ ? Math . max ( 0 , Math . min ( 1 , f . confidence_score > 1 ? f . confidence_score / 10 : f . confidence_score ) )
190193 : undefined ,
191194 } ;
192195}
@@ -288,7 +291,7 @@ export function parseFileReviewResponse(raw: string, file: FileDiff): {
288291 logger . warn ( 'jsonrepair failed to fix model output, using preprocessed text' , { preprocessed : truncateJsonForLog ( preprocessed ) , error : e } ) ;
289292 }
290293
291- let parsedJson : any ;
294+ let parsedJson : unknown ;
292295 try {
293296 parsedJson = JSON . parse ( repaired ) ;
294297 } catch ( e ) {
@@ -298,13 +301,13 @@ export function parseFileReviewResponse(raw: string, file: FileDiff): {
298301
299302 let parsed : z . infer < typeof fileReviewModelOutputSchema > ;
300303 try {
301- const findReviewObject = ( arr : any [ ] ) : any | null => {
304+ const findReviewObject = ( arr : unknown [ ] ) : unknown | null => {
302305 // Priority 1: Has findings array and summary
303- const best = arr . find ( i => i && typeof i === 'object' && Array . isArray ( i . findings ) && typeof i . summary === 'string' ) ;
306+ const best = arr . find ( i => i && typeof i === 'object' && Array . isArray ( ( i as Record < string , unknown > ) . findings ) && typeof ( i as Record < string , unknown > ) . summary === 'string' ) ;
304307 if ( best ) return best ;
305308
306309 // Priority 2: Has findings array
307- const good = arr . find ( i => i && typeof i === 'object' && Array . isArray ( i . findings ) ) ;
310+ const good = arr . find ( i => i && typeof i === 'object' && Array . isArray ( ( i as Record < string , unknown > ) . findings ) ) ;
308311 if ( good ) return good ;
309312
310313 // Priority 3: Has review-like keys
@@ -314,29 +317,31 @@ export function parseFileReviewResponse(raw: string, file: FileDiff): {
314317 ) ;
315318 } ;
316319
317- const data = Array . isArray ( parsedJson ) ? ( findReviewObject ( parsedJson ) || parsedJson [ 0 ] || { } ) : parsedJson ;
320+ let data = Array . isArray ( parsedJson ) ? ( findReviewObject ( parsedJson ) || parsedJson [ 0 ] || { } ) : parsedJson ;
318321
319322 // Ensure essential keys exist to avoid schema validation errors
320323 if ( data && typeof data === 'object' ) {
321- if ( ! data . findings ) data . findings = [ ] ;
322- if ( ! data . overall_explanation ) data . overall_explanation = 'No explanation provided.' ;
323- if ( ! data . overall_correctness ) data . overall_correctness = 'Uncertain' ;
324+ const obj = data as Record < string , unknown > ;
325+ if ( ! obj . findings ) obj . findings = [ ] ;
326+ if ( ! obj . overall_explanation ) obj . overall_explanation = 'No explanation provided.' ;
327+ if ( ! obj . overall_correctness ) obj . overall_correctness = 'Uncertain' ;
324328
325329 // Handle confidence score hallucinations (0-1 range expected)
326- if ( typeof data . overall_confidence_score === 'number' ) {
327- if ( data . overall_confidence_score > 1 ) {
330+ if ( typeof obj . overall_confidence_score === 'number' ) {
331+ if ( obj . overall_confidence_score > 1 ) {
328332 // If they gave 1-10 scale, normalize it
329- data . overall_confidence_score = Math . min ( data . overall_confidence_score / 10 , 1 ) ;
330- } else if ( data . overall_confidence_score < 0 ) {
331- data . overall_confidence_score = 0 ;
333+ obj . overall_confidence_score = Math . min ( obj . overall_confidence_score / 10 , 1 ) ;
334+ } else if ( obj . overall_confidence_score < 0 ) {
335+ obj . overall_confidence_score = 0 ;
332336 }
333337 } else {
334- data . overall_confidence_score = 0.5 ;
338+ obj . overall_confidence_score = 0.5 ;
335339 }
336340
337- if ( Array . isArray ( data . findings ) ) {
338- data . findings = data . findings . map ( normalizeFinding ) . filter ( Boolean ) ;
341+ if ( Array . isArray ( obj . findings ) ) {
342+ obj . findings = obj . findings . map ( normalizeFinding ) . filter ( Boolean ) ;
339343 }
344+ data = obj ;
340345 }
341346
342347 parsed = fileReviewModelOutputSchema . parse ( data ) ;
0 commit comments