@@ -29,6 +29,63 @@ public AgenticMesh(AgentCatalog agentCatalog) {
2929
3030 }
3131
32+ /**
33+ * Extracts the first valid JSON object from a response that may contain multiple JSONs or extra text.
34+ * Handles markdown code blocks and commentary from LLM.
35+ * @param response The response string that may contain multiple JSON objects
36+ * @return First valid JSON object as string, or original response if no JSON found
37+ */
38+ private String extractFirstJsonObject (String response ) {
39+ if (response == null || response .trim ().isEmpty ()) {
40+ return response ;
41+ }
42+
43+ String cleaned = response .trim ();
44+
45+ // Remove markdown code blocks first
46+ if (cleaned .contains ("```json" )) {
47+ int startIdx = cleaned .indexOf ("```json" ) + 7 ;
48+ int endIdx = cleaned .indexOf ("```" , startIdx );
49+ if (endIdx > startIdx ) {
50+ cleaned = cleaned .substring (startIdx , endIdx ).trim ();
51+ }
52+ } else if (cleaned .startsWith ("```" )) {
53+ int startIdx = cleaned .indexOf ("```" ) + 3 ;
54+ int endIdx = cleaned .indexOf ("```" , startIdx );
55+ if (endIdx > startIdx ) {
56+ cleaned = cleaned .substring (startIdx , endIdx ).trim ();
57+ }
58+ }
59+
60+ // Find first { and matching }
61+ int firstBrace = cleaned .indexOf ('{' );
62+ if (firstBrace == -1 ) {
63+ return response ;
64+ }
65+
66+ int braceCount = 0 ;
67+ int endIdx = -1 ;
68+
69+ for (int i = firstBrace ; i < cleaned .length (); i ++) {
70+ char c = cleaned .charAt (i );
71+ if (c == '{' ) {
72+ braceCount ++;
73+ } else if (c == '}' ) {
74+ braceCount --;
75+ if (braceCount == 0 ) {
76+ endIdx = i ;
77+ break ;
78+ }
79+ }
80+ }
81+
82+ if (endIdx > firstBrace ) {
83+ return cleaned .substring (firstBrace , endIdx + 1 );
84+ }
85+
86+ return response ;
87+ }
88+
3289 public CommonClientResponse pipeLineMesh (String query ){
3390 return pipeLineMesh (query , null );
3491 }
@@ -50,18 +107,37 @@ public CommonClientResponse pipeLineMesh(String query, CommonClientResponse prev
50107 return previousResponse ;
51108 } else {
52109 try {
53- jsonYesOrNo = promptTransformer .transformIntoJson (jsonUtils .createJson (yesOrNoField ,pendingQuery ).toString (),"Original query " +query + " response " +response +" " );
110+ String prompt = "Original query: " + query + " response: " + response + ". IMPORTANT: Return ONLY a single JSON object, no explanations, no multiple JSONs, no markdown formatting." ;
111+ jsonYesOrNo = promptTransformer .transformIntoJson (
112+ jsonUtils .createJson (yesOrNoField , pendingQuery ).toString (),
113+ prompt
114+ );
115+
116+ // Extract first valid JSON object
117+ jsonYesOrNo = extractFirstJsonObject (jsonYesOrNo );
118+ log .debug ("Extracted JSON: {}" , jsonYesOrNo );
54119
55120 String yesOrNo = jsonUtils .getFieldValueFromMultipleFields (jsonYesOrNo , yesOrNoField );
56- if (yesOrNo .contains ("Yes" )) {
121+ if (yesOrNo != null && yesOrNo .contains ("Yes" )) {
57122 return response ;
58- } else {
123+ } else if ( yesOrNo != null ) {
59124 String pendingQueryValue = jsonUtils .getFieldValueFromMultipleFields (jsonYesOrNo , pendingQuery );
60- response = pipeLineMesh ("Pending query " +pendingQueryValue + " response " +response .getTextResult () ,response );
125+ if (pendingQueryValue != null && !pendingQueryValue .trim ().isEmpty ()) {
126+ response = pipeLineMesh ("Pending query: " + pendingQueryValue + " previous response: " + response .getTextResult (), response );
127+ } else {
128+ return response ;
129+ }
130+ } else {
131+ log .warn ("Could not extract yes/no answer, returning current response" );
132+ return response ;
61133 }
62134
63135 } catch (AIProcessingException e ) {
64- log .warn (e .getMessage ());
136+ log .warn ("AIProcessingException in pipeLineMesh: {}" , e .getMessage ());
137+ return response ;
138+ } catch (Exception e ) {
139+ log .error ("Unexpected error in pipeLineMesh: {}" , e .getMessage (), e );
140+ return response ;
65141 }
66142
67143 }
@@ -86,10 +162,13 @@ public CommonClientResponse hubAndSpoke(String query) {
86162
87163 try {
88164 // Get list of sub-queries needed
165+ String prompt = "Original query: " + query + " Initial response: " + mainResponse .getTextResult () + ". IMPORTANT: Return ONLY a single JSON object, no explanations." ;
89166 jsonQueries = promptTransformer .transformIntoJson (
90167 jsonUtils .createJson (subQueriesField ).toString (),
91- "Original query: " + query + " Initial response: " + mainResponse . getTextResult ()
168+ prompt
92169 );
170+
171+ jsonQueries = extractFirstJsonObject (jsonQueries );
93172
94173 String subQueriesString = jsonUtils .getFieldValueFromMultipleFields (jsonQueries , subQueriesField );
95174 if (subQueriesString == null || subQueriesString .isEmpty ()) {
@@ -136,10 +215,13 @@ public CommonClientResponse blackboard(String query) {
136215
137216 try {
138217 // Identify knowledge gaps and required expert agents
218+ String prompt = "Analyze knowledge gaps and required experts for: " + initialKnowledge .getTextResult () + ". IMPORTANT: Return ONLY a single JSON object, no explanations." ;
139219 jsonAnalysis = promptTransformer .transformIntoJson (
140220 jsonUtils .createJson (knowledgeGapsField , expertAgentsField ).toString (),
141- "Analyze knowledge gaps and required experts for: " + initialKnowledge . getTextResult ()
221+ prompt
142222 );
223+
224+ jsonAnalysis = extractFirstJsonObject (jsonAnalysis );
143225
144226 String gaps = jsonUtils .getFieldValueFromMultipleFields (jsonAnalysis , knowledgeGapsField );
145227 String experts = jsonUtils .getFieldValueFromMultipleFields (jsonAnalysis , expertAgentsField );
0 commit comments