@@ -487,6 +487,7 @@ export class AgentBlockHandler implements BlockHandler {
487487 const contentType = response . headers . get ( 'Content-Type' )
488488 if ( contentType ?. includes ( 'text/event-stream' ) ) {
489489 // Handle streaming response
490+ logger . info ( 'Received streaming response' )
490491 return this . handleStreamingResponse ( response , block )
491492 }
492493
@@ -705,119 +706,28 @@ export class AgentBlockHandler implements BlockHandler {
705706 private processStructuredResponse ( result : any , responseFormat : any ) : BlockOutput {
706707 const content = result . content
707708
708- const extractedJson = this . extractJsonFromContent ( content )
709-
710- if ( extractedJson !== null ) {
709+ try {
710+ const extractedJson = JSON . parse ( content . trim ( ) )
711711 logger . info ( 'Successfully parsed structured response content' )
712712 return {
713713 ...extractedJson ,
714714 ...this . createResponseMetadata ( result ) ,
715715 }
716- }
717-
718- // All parsing attempts failed
719- logger . error ( 'Failed to parse response content as JSON:' , {
720- content : content . substring ( 0 , 200 ) + ( content . length > 200 ? '...' : '' ) ,
721- responseFormat : responseFormat ,
722- } )
723-
724- // Return standard response but include a warning
725- const standardResponse = this . processStandardResponse ( result )
726- return Object . assign ( standardResponse , {
727- _responseFormatWarning :
728- 'Response format was specified but content could not be parsed as JSON. Falling back to standard format.' ,
729- } )
730- }
731-
732- private extractJsonFromContent ( content : string ) : any | null {
733- // Strategy 1: Direct JSON parsing
734- try {
735- return JSON . parse ( content . trim ( ) )
736- } catch {
737- // Continue to next strategy
738- }
739-
740- // Strategy 2: Extract from markdown code blocks (most common case)
741- // Matches ```json ... ``` or ``` ... ```
742- const codeBlockRegex = / ` ` ` (?: j s o n ) ? \s * ( [ \s \S ] * ?) \s * ` ` ` /
743- const codeBlockMatch = content . match ( codeBlockRegex )
744- if ( codeBlockMatch ?. [ 1 ] ) {
745- try {
746- return JSON . parse ( codeBlockMatch [ 1 ] . trim ( ) )
747- } catch {
748- // Continue to next strategy
749- }
750- }
751-
752- // Strategy 3: Find first complete JSON object/array in the text
753- // Look for { ... } or [ ... ] with proper bracket matching
754- const jsonObjectMatch = this . findCompleteJsonInText ( content )
755- if ( jsonObjectMatch ) {
756- try {
757- return JSON . parse ( jsonObjectMatch )
758- } catch {
759- // Continue to next strategy
760- }
761- }
762-
763- return null
764- }
765-
766- private findCompleteJsonInText ( text : string ) : string | null {
767- const trimmed = text . trim ( )
768-
769- // Find first { or [
770- let startIndex = - 1
771- let startChar = ''
772-
773- for ( let i = 0 ; i < trimmed . length ; i ++ ) {
774- if ( trimmed [ i ] === '{' || trimmed [ i ] === '[' ) {
775- startIndex = i
776- startChar = trimmed [ i ]
777- break
778- }
779- }
780-
781- if ( startIndex === - 1 ) {
782- return null
783- }
784-
785- const endChar = startChar === '{' ? '}' : ']'
786- let depth = 0
787- let inString = false
788- let escaped = false
789-
790- for ( let i = startIndex ; i < trimmed . length ; i ++ ) {
791- const char = trimmed [ i ]
792-
793- if ( escaped ) {
794- escaped = false
795- continue
796- }
797-
798- if ( char === '\\' ) {
799- escaped = true
800- continue
801- }
716+ } catch ( error ) {
717+ logger . info ( 'JSON parsing failed' , { error : error instanceof Error ? error . message : 'Unknown error' } )
802718
803- if ( char === '"' && ! escaped ) {
804- inString = ! inString
805- continue
806- }
719+ // LLM did not adhere to structured response format
720+ logger . error ( 'LLM did not adhere to structured response format:' , {
721+ content : content . substring ( 0 , 200 ) + ( content . length > 200 ? '...' : '' ) ,
722+ responseFormat : responseFormat ,
723+ } )
807724
808- if ( ! inString ) {
809- if ( char === startChar ) {
810- depth ++
811- } else if ( char === endChar ) {
812- depth --
813- if ( depth === 0 ) {
814- return trimmed . substring ( startIndex , i + 1 )
815- }
816- }
817- }
725+ const standardResponse = this . processStandardResponse ( result )
726+ return Object . assign ( standardResponse , {
727+ _responseFormatWarning :
728+ 'LLM did not adhere to the specified structured response format. Expected valid JSON but received malformed content. Falling back to standard format.' ,
729+ } )
818730 }
819-
820- return null
821731 }
822732
823733 private processStandardResponse ( result : any ) : BlockOutput {
0 commit comments