luigidemasi commented on code in PR #150:
URL: https://github.com/apache/camel-kit/pull/150#discussion_r4491373895


##########
kit/camel-kit-core/src/main/java/org/apache/camel/kit/ship/controller/ShipStageResult.java:
##########
@@ -280,6 +281,134 @@ private static void requireReport(String report) throws 
IOException {
         utf8(report, MAX_REPORT_BYTES, "stage report");
     }
 
+    private static String extractJsonObject(String text) throws IOException {
+        if (text == null) {
+            return text;
+        }
+        String stripped = text.strip();
+        if (stripped.startsWith("{")) {
+            return stripped;
+        }
+        String fenced = extractFencedJson(text);
+        if (fenced != null) {
+            return fenced;
+        }
+        int start = text.indexOf('{');
+        int end = text.lastIndexOf('}');
+        if (start >= 0 && end > start) {
+            String prefix = text.substring(0, start).strip();
+            if (!prefix.isEmpty() && prefix.indexOf('[') >= 0) {
+                throw new IOException("Pi stage result is wrapped in an 
array");
+            }
+            return text.substring(start, end + 1);
+        }
+        return stripped;
+    }
+
+    private static String extractFencedJson(String text) throws IOException {
+        String result = null;
+        int regionStart = -1;
+        int regionEnd = -1;
+        int pos = 0;
+        int len = text.length();
+
+        while (pos < len) {
+            int tick = text.indexOf("```", pos);
+            if (tick < 0) {
+                break;
+            }
+            if (tick > 0 && text.charAt(tick - 1) != '\n') {
+                pos = tick + 3;
+                continue;
+            }
+            int cur = tick + 3;
+            if (cur + 4 <= len && text.startsWith("json", cur)) {
+                cur += 4;
+            }
+            while (cur < len && (text.charAt(cur) == ' ' || text.charAt(cur) 
== '\t')) {
+                cur++;
+            }
+            if (cur >= len || text.charAt(cur) != '\n') {
+                pos = tick + 3;
+                continue;
+            }
+            int contentStart = cur + 1;
+
+            int close = contentStart;
+            boolean found = false;
+            while (true) {
+                close = text.indexOf("\n```", close);
+                if (close < 0) {
+                    break;
+                }
+                int afterClose = close + 4;
+                if (afterClose >= len || text.charAt(afterClose) == '\n') {
+                    found = true;
+                    break;
+                }
+                close = afterClose;
+            }
+            if (!found) {
+                break;
+            }
+
+            String content = text.substring(contentStart, close).strip();
+            int end = close + 4;
+            if (end < len && text.charAt(end) == '\n') {
+                end++;
+            }
+
+            if (content.startsWith("{") && content.endsWith("}")) {
+                if (result != null) {
+                    throw new IOException("Pi stage result contains 
conflicting fenced JSON envelopes");
+                }
+                result = content;
+                regionStart = tick;
+                regionEnd = end;
+            }
+            pos = end;
+        }
+
+        if (result == null) {
+            return null;
+        }
+        String before = text.substring(0, regionStart);
+        String after = text.substring(regionEnd);
+        if (hasBareJsonStart(before) || hasBareJsonStart(after)) {
+            throw new IOException("Pi stage result contains conflicting JSON 
envelopes");
+        }
+        return result;
+    }
+
+    private static final String ENVELOPE_MARKER = "\"materialAmbiguity\"";
+
+    private static boolean hasBareJsonStart(String fragment) {
+        int i = 0;
+        int len = fragment.length();
+        while (i < len) {
+            char c = fragment.charAt(i);
+            if (c == '`') {
+                int j = i + 1;
+                while (j < len && fragment.charAt(j) != '`' && 
fragment.charAt(j) != '\n') {
+                    j++;
+                }
+                if (j < len && fragment.charAt(j) == '`') {
+                    String span = fragment.substring(i + 1, j);
+                    if (span.contains(ENVELOPE_MARKER)) {
+                        return true;

Review Comment:
   [P2] Recognize decoded JSON field names in inline envelopes
   
   The literal substring check still misses a complete stage-result envelope 
when its field name uses valid JSON escaping. In the existing inline-correction 
reproducer, change only `"materialAmbiguity"` to `"\u006daterialAmbiguity"`. 
Jackson decodes both to the same field: the escaped correction alone parses 
with `materialAmbiguity=true` and one unanswered question, and the real 
coordinator pauses under SMART. Appended inside backticks after the earlier 
fenced result, however, the marker is absent from the raw span, so the 
correction is discarded; DESIGN completes with zero questions and PLAN starts 
(one attempt).
   
   The exact unescaped reproducer is fixed, but this equivalent encoding 
retains the same ambiguity failure. The base parser and `352b4589` reject the 
mixed response. Please inspect candidate inline JSON with the existing strict 
JSON mapper, or use a wrapper rule that cannot hide another envelope, rather 
than relying on one raw key spelling. Add the escaped-key mixed response and 
its raw-correction control while keeping the harmless inline status example 
accepted. The coordinator probe uses the existing Pi RPC fixture; it 
establishes stage advancement, not workflow publication.
   
   _AI-generated by Codex on behalf of @luigidemasi._
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to