gnodet-bot commented on code in PR #27512:
URL: https://github.com/apache/camel/pull/27512#discussion_r4209611170


##########
dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogService.java:
##########
@@ -79,8 +79,21 @@ public CamelCatalog getDefaultCatalog() {
     public CamelCatalog loadCatalog(String runtime, String camelVersion, 
String platformBom) throws Exception {
         RuntimeType runtimeType = resolveRuntime(runtime);
 
-        boolean hasVersion = camelVersion != null && !camelVersion.isBlank();
+        // "main", "latest", "current" or "default" (what an assistant writes 
when it means the version in use) is
+        // the default catalog, not a version to download
+        boolean hasVersion = camelVersion != null && !camelVersion.isBlank() 
&& !camelVersion.isEmpty()

Review Comment:
   🔵 **Low — Redundant `isEmpty()` check:** `isBlank()` returns `true` for both 
empty and blank strings, so `!camelVersion.isBlank()` being `true` already 
guarantees `!camelVersion.isEmpty()` is `true`. The `isEmpty()` check is never 
reached when `isBlank()` is false.
   
   ```suggestion
           boolean hasVersion = camelVersion != null && !camelVersion.isBlank()
   ```



##########
dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/MigrationTools.java:
##########
@@ -211,11 +212,12 @@ public CompatibilityResult camel_migration_compatibility(
                         + "BEFORE running the OpenRewrite recipes. If the 
project does not compile, fix the build "
                         + "errors first. OpenRewrite requires a compilable 
project to parse and transform the code.")
     public MigrationRecipesResult camel_migration_recipes(
-            @ToolArg(description = ToolArgDocs.RUNTIME_REQUIRED) String 
runtime,
+            @ToolArg(description = ToolArgDocs.RUNTIME_REQUIRED, required = 
false) String runtime,

Review Comment:
   ⚠️ **High — Schema contradiction:** The annotation says `required = false`, 
but the description uses `ToolArgDocs.RUNTIME_REQUIRED` (the constant name 
literally says REQUIRED) and the method body immediately throws if `runtime` is 
null or blank. An LLM client reading the JSON schema will see the parameter as 
optional and may omit it — resulting in a `ToolCallException`. Either set 
`required = true` here (matching the null-guard), or update the guard to handle 
the missing case gracefully.
   
   ```suggestion
               @ToolArg(description = ToolArgDocs.RUNTIME_REQUIRED) String 
runtime,
   ```



##########
dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogService.java:
##########
@@ -121,11 +134,38 @@ public CamelCatalog loadCatalog(String runtime, String 
camelVersion, String plat
             return cached;
         }
 
-        CamelCatalog loaded = doLoadCatalog(runtimeType, camelVersion, 
platformBomGav);
+        CamelCatalog loaded;
+        try {
+            loaded = doLoadCatalog(runtimeType, camelVersion, platformBomGav);
+        } catch (Exception e) {
+            if (runtimeType == RuntimeType.main && hasVersion && !hasBom) {
+                // a version that cannot be downloaded (not released, no 
network): answer from the default catalog
+                // rather than fail the tool call
+                return defaultCatalog;

Review Comment:
   🟡 **Medium — Silent fallback with no logging:** When a version cannot be 
downloaded, `defaultCatalog` is returned silently. A user passing e.g. 
`camelVersion="4.99.0"` will get back the default catalog version with no 
warning or indication that the requested version wasn't found. Consider adding 
at least a `LOG.warn("Could not load catalog for version {}, falling back to 
default: {}", camelVersion, e.getMessage())` before the return.



##########
dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/RuntimeTools.java:
##########
@@ -394,18 +400,24 @@ For deep analysis, use a full heap dump (jmap -dump:live) 
with tools like Eclips
                   Entries with lowConfidence=true have unreliable growth 
percentages due to low sample counts or \
                   sample counts that diverge significantly between runs — 
recommend a longer recording duration.""")
     public JsonObject camel_runtime_memory_leak(
-            @ToolArg(description = NAME_OR_PID_DESC) String nameOrPid,
+            @ToolArg(description = NAME_OR_PID_DESC, required = false) String 
nameOrPid,
             @ToolArg(description = "Command: start, stop, status, or query") 
String command,
-            @ToolArg(description = "Recording duration in seconds (only for 
start command, default 60, use 0 for manual stop)") String duration,
-            @ToolArg(description = "Recording mode: dual (default, two 
recordings at Xs and 2Xs with trend comparison) or single (one recording)") 
String mode,
-            @ToolArg(description = "Include allocation stack traces in results 
(default false, set true for detailed analysis)") String stacktrace,
-            @ToolArg(description = "Minimum total size in bytes to include a 
sample (e.g. 1024 for 1KB). Filters out small allocations to reduce noise. 
Default 1024 (1KB) in dual mode") String minSize) {
+            @ToolArg(description = "Recording duration in seconds (only for 
start command, default 60, use 0 for manual stop)",
+                     required = false) String duration,
+            @ToolArg(description = "Recording mode: dual (default, two 
recordings at Xs and 2Xs with trend comparison) or single (one recording)",
+                     required = false) String mode,
+            @ToolArg(description = "Include allocation stack traces in results 
(default false, set true for detailed analysis)",
+                     required = false) String stacktrace,
+            @ToolArg(description = "Minimum total size in bytes to include a 
sample (e.g. 1024 for 1KB). Filters out small allocations to reduce noise. 
Default 1024 (1KB) in dual mode",
+                     required = false) String minSize) {
         if (command == null || command.isBlank()) {
             throw new ToolCallException("command is required (start, stop, 
status, or query)", null);
         }
         RuntimeService.ProcessInfo p = 
runtimeService.findSingleProcess(nameOrPid);
 
-        if ("start".equals(command) && "dual".equalsIgnoreCase(mode)) {
+        // dual is the documented default: an omitted or blank mode records 
twice too
+        boolean dual = mode == null || mode.isBlank() || 
"dual".equalsIgnoreCase(mode);

Review Comment:
   🔵 **Low — Behavioral change not covered by a test:** When `mode` is `null` 
or blank (i.e., the argument is omitted), this now triggers dual recording. 
Previously omitting `mode` was a no-op. The PR description documents this as 
intentional, but there's no new test asserting that `mode=null` → dual path. 
Worth adding a test case.



##########
dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogService.java:
##########
@@ -121,11 +134,38 @@ public CamelCatalog loadCatalog(String runtime, String 
camelVersion, String plat
             return cached;
         }
 
-        CamelCatalog loaded = doLoadCatalog(runtimeType, camelVersion, 
platformBomGav);
+        CamelCatalog loaded;
+        try {
+            loaded = doLoadCatalog(runtimeType, camelVersion, platformBomGav);
+        } catch (Exception e) {
+            if (runtimeType == RuntimeType.main && hasVersion && !hasBom) {
+                // a version that cannot be downloaded (not released, no 
network): answer from the default catalog
+                // rather than fail the tool call
+                return defaultCatalog;
+            }
+            throw e;
+        }
         cache.putIfAbsent(key, loaded);
         return cache.get(key);
     }
 
+    /** Whether the value is an org.apache.camel groupId:artifactId:version 
GAV. */
+    static boolean isCamelGav(String gav) {
+        String[] parts = gav.trim().split(":");
+        return parts.length == 3 && "org.apache.camel".equals(parts[0].trim()) 
&& !parts[1].isBlank() && !parts[2].isBlank();
+    }
+
+    /** Whether the version is the default catalog's, with or without a 
-SNAPSHOT qualifier. */
+    boolean sameAsDefault(String camelVersion) {
+        String mine = defaultCatalog.getCatalogVersion();
+        if (mine == null) {
+            return false;
+        }
+        String v = camelVersion.trim();
+        return v.equals(mine) || v.equals(mine.replace("-SNAPSHOT", ""))
+                || mine.equals(v.replace("-SNAPSHOT", ""));

Review Comment:
   🔵 **Low — Third arm intent is non-obvious:** 
`mine.equals(v.replace("-SNAPSHOT", ""))` handles the case where the user asks 
for `4.22.0-SNAPSHOT` and the default is `4.22.0` (the inverse of the second 
arm). A brief comment would help readers understand why both directions are 
needed:
   
   ```suggestion
           // second arm: user asks for 4.22.0, default is 4.22.0-SNAPSHOT → 
same
           // third arm: user asks for 4.22.0-SNAPSHOT, default is 4.22.0 → same
           return v.equals(mine) || v.equals(mine.replace("-SNAPSHOT", ""))
                   || mine.equals(v.replace("-SNAPSHOT", ""));
   ```



-- 
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