This is an automated email from the ASF dual-hosted git repository. luigidemasi pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-kit.git
commit 619cd532fc22d9e7efd2aafecd8b717ba3be8b88 Author: Jinal Sarvaiya <[email protected]> AuthorDate: Mon Nov 2 14:51:54 2026 +0000 fix #100: handle Pi markdown-wrapped stage JSON in ShipStageResult parser --- .../camel/kit/ship/controller/ShipStageResult.java | 26 +++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/kit/camel-kit-core/src/main/java/org/apache/camel/kit/ship/controller/ShipStageResult.java b/kit/camel-kit-core/src/main/java/org/apache/camel/kit/ship/controller/ShipStageResult.java index 7b9f02fb..ca0e43e4 100644 --- a/kit/camel-kit-core/src/main/java/org/apache/camel/kit/ship/controller/ShipStageResult.java +++ b/kit/camel-kit-core/src/main/java/org/apache/camel/kit/ship/controller/ShipStageResult.java @@ -10,6 +10,7 @@ import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.camel.kit.ship.artifact.ArtifactManifest.JavaPolicy; @@ -47,6 +48,8 @@ record ShipStageResult( private static final int MAX_ASSISTANT_BYTES = 1024 * 1024; private static final int MAX_REPORT_BYTES = MAX_ASSISTANT_BYTES; private static final Pattern ROUTE_ID = Pattern.compile("[A-Za-z0-9][A-Za-z0-9_.-]{0,127}"); + private static final Pattern JSON_FENCE = Pattern.compile( + "```(?:json)?\\s*\\n(\\{.*?\\})\\s*\\n```", Pattern.DOTALL); private static final Comparator<RouteContract> ROUTE_ORDER = Comparator .comparing(RouteContract::routeId) .thenComparing(RouteContract::routePath) @@ -77,8 +80,9 @@ record ShipStageResult( WireResult wire; boolean legacy = false; try { + String normalized = extractJsonObject(assistantText); JsonNode document - = JSON.readValue(utf8(assistantText, MAX_ASSISTANT_BYTES, "assistant response"), JsonNode.class); + = JSON.readValue(utf8(normalized, MAX_ASSISTANT_BYTES, "assistant response"), JsonNode.class); if (document instanceof ObjectNode object && object.path("schemaVersion").isIntegralNumber() && object.path("schemaVersion").intValue() == 1) { legacy = true; @@ -280,6 +284,26 @@ record ShipStageResult( utf8(report, MAX_REPORT_BYTES, "stage report"); } + private static String extractJsonObject(String text) { + if (text == null) { + return text; + } + String stripped = text.strip(); + if (stripped.startsWith("{")) { + return stripped; + } + Matcher m = JSON_FENCE.matcher(text); + if (m.find()) { + return m.group(1).strip(); + } + int start = text.indexOf('{'); + int end = text.lastIndexOf('}'); + if (start >= 0 && end > start) { + return text.substring(start, end + 1); + } + return stripped; + } + static byte[] utf8(String value, int maximum, String label) throws IOException { if (value == null || value.length() > maximum) { throw new IOException("Pi " + label + " exceeds its size limit");
