CAMEL-24566: Auto-discover GenAI dependencies in Camel CLI - #26055
CAMEL-24566: Auto-discover GenAI dependencies in Camel CLI#26055atiaomar1978-hub wants to merge 5 commits into
Conversation
Add GenAiDependencyDiscovery to scan route URIs and LangChain4j provider classes for camel-jbang run, export, dependency list and dependency update. - Add camel:ai-observability when GenAI routes are detected (unless disabled) - Add LangChain4j provider JAR mappings to known-dependencies.properties - Integrate discovery into Run and ExportBaseCommand.resolveDependencies Co-authored-by: Cursor Agent <cursoragent@cursor.com>
- Make ai-observability opt-in via --observe or camel.aiObservability.enabled=true - Load LangChain4j provider mappings from known-dependencies (package keys) - Scope URI extraction by file type and ignore YAML comments/false positives - Fix settings file scanning for export dependency resolution Co-authored-by: Cursor Agent <cursoragent@cursor.com>
aedcb7f to
023e9c6
Compare
davsclaus
left a comment
There was a problem hiding this comment.
No we should not scan the code, we need to find another way that is more similar to what we already do
…ncy resolution Remove GenAiDependencyDiscovery regex scanning of YAML/XML/Java routes. GenAI components and LangChain4j providers are resolved through the existing silent-run download pipeline (DependencyDownloaderComponentResolver and KnownDependenciesResolver), matching OpenTelemetry and LRA handling. - Add GenAiDependencyHelper to conditionally add camel:ai-observability from settings/profile when GenAI artifacts are already present - Map GenAiObservabilityImpl in camel-main-known-dependencies.properties - Replace unit tests with GenAiDependencyHelperTest Co-authored-by: Cursor <cursoragent@cursor.com>
|
Addressed review feedback in New approach (aligned with existing JBang patterns):
Removed Cursor Agent on behalf of atiaomar1978-hub |
atiaomar1978-hub
left a comment
There was a problem hiding this comment.
Thanks @davsclaus — agreed, route source scanning is removed in 04413ce. GenAI dependencies now use the same silent-run + catalog + known-deps pipeline as other components. Only camel-ai-observability uses a small settings helper (OpenTelemetry/LRA style).
Cursor Agent on behalf of atiaomar1978-hub
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
✅ Generated files are up to dateAn earlier CI run reported uncommitted generated changes; the latest run no longer does. |
|
🧪 CI tested the following changed modules:
🔬 Scalpel shadow comparison — Scalpel: 8 tested, 8 compile-only — current: 6 all testedMaveniverse Scalpel detected 16 affected modules (current approach: 6).
|
gnodet
left a comment
There was a problem hiding this comment.
Reviewed the current diff (after the 04413ce rework that removed route source scanning). The approach now correctly relies on the existing silent-run + catalog + KnownDependenciesResolver pipeline for GenAI components/providers, with GenAiDependencyHelper only handling the camel-ai-observability opt-in — consistent with how OpenTelemetry and LRA are handled. A few observations below.
This review was generated by an AI agent, Hermès, on behalf of @gnodet.
| private static boolean isAiArtifactId(String dep) { | ||
| int idx = dep.indexOf(":camel-"); | ||
| if (idx < 0) { | ||
| return false; |
There was a problem hiding this comment.
isAiArtifactId uses artifact.startsWith("camel-ai-") which matches camel-ai-observability itself. If a user adds mvn:org.apache.camel:camel-ai-observability:... as an explicit --dep, hasGenAiDependency returns true, and the method would add camel:ai-observability again as a duplicate.
In ExportBaseCommand this is harmless (TreeSet dedup), but in Run.java dependencies is an ArrayList, so it results in a duplicate entry. Not a crash-level issue — the downstream dependency resolution likely handles it — but it's an unintended self-reference.
Consider excluding camel-ai-observability explicitly, or using the catalog label check as the primary filter for mvn: deps too.
There was a problem hiding this comment.
Fixed in 054c4fd: mvn: GenAI detection now uses CamelCatalog.modelFromMavenGAV() plus the catalog ai label. camel-ai-observability is explicitly excluded from hasGenAiDependency(), and alreadyHasAiObservability() prevents duplicate camel:ai-observability entries in Run.java ArrayList.
Cursor Agent on behalf of atiaomar1978-hub
| return artifact.startsWith("camel-langchain4j") | ||
| || artifact.startsWith("camel-openai") | ||
| || artifact.startsWith("camel-spring-ai") | ||
| || artifact.startsWith("camel-aws-bedrock") |
There was a problem hiding this comment.
The contains("-ai-") check is broad. Today's component names are safe, but future non-AI components with -ai- in their artifact ID (e.g., a hypothetical camel-repair-aid-connector) would be false-positived here. The catalog label check (isAiLabel) is the authoritative source of truth — could the mvn: branch also query the catalog by artifact ID instead of relying on string heuristics?
There was a problem hiding this comment.
Fixed in 054c4fd: removed contains("-ai-") and prefix heuristics entirely. The mvn: branch now parses the GAV and queries the catalog via modelFromMavenGAV(), using the ai label as the authoritative check.
Cursor Agent on behalf of atiaomar1978-hub
| dev.langchain4j.model.vertexai = dev.langchain4j:langchain4j-vertex-ai:${langchain4j-version} | ||
| dev.langchain4j.model.googleai = dev.langchain4j:langchain4j-google-ai-gemini:${langchain4j-version} | ||
| dev.langchain4j.model.github = dev.langchain4j:langchain4j-github-models:${langchain4j-version} | ||
| dev.langchain4j.model.embedding.onnx = dev.langchain4j:langchain4j-embeddings:${langchain4j-beta-version} |
There was a problem hiding this comment.
The last two entries use a different convention from the rest of the file:
org.apache.camel.component.ai.observability.GenAiObservabilityImpl = camel:ai-observability
camel.aiObservability = camel:ai-observability
Existing entries in this file are keyed by either fully-qualified class names or property keys with = escaping (e.g., org.apache.camel.component.activemq.ActiveMQComponent\:embedded\=true). The camel.aiObservability entry is a camel-main property prefix, not a class name — KnownDependenciesResolver.findGav() does prefix-trimming on . separators, so this entry would match any property or class starting with camel.aiObservability. Is this intentional? It means any camel.aiObservability.* property access through the properties component triggers a download of camel:ai-observability, which seems like the desired behavior but is worth calling out since it's a novel use of the known-deps file.
There was a problem hiding this comment.
Yes, intentional — same pattern as camel.opentelemetry / camel.lra (lines 43-47). Added an inline comment in 054c4fd documenting that camel.aiObservability is a camel-main property prefix so any camel.aiObservability.* access triggers runtime download of camel:ai-observability.
Cursor Agent on behalf of atiaomar1978-hub
| * </p> | ||
| */ | ||
| public final class GenAiDependencyHelper { | ||
|
|
There was a problem hiding this comment.
Nit: the constant AI_OBSERVABILITY_ENABLED is public but is only used within this class and in tests (which access package-private methods anyway). Consider narrowing to package-private if there's no external consumer planned.
There was a problem hiding this comment.
Done in 054c4fd — AI_OBSERVABILITY_ENABLED is now package-private.
Cursor Agent on behalf of atiaomar1978-hub
| GenAiDependencyHelper.addAiObservabilityIfNeeded(deps, properties, true, catalog); | ||
|
|
||
| assertThat(deps).doesNotContain("camel:ai-observability"); | ||
| } |
There was a problem hiding this comment.
This test mocks the catalog to return a ComponentModel with label "ai" for "openai" — but the real catalog already has openai with label "ai" (verified in components/camel-ai/camel-openai/src/generated/resources/). Using the real DefaultCamelCatalog here (like the other tests) would be more resilient to future catalog changes and wouldn't require Mockito.
There was a problem hiding this comment.
Done in 054c4fd — replaced the Mockito mock with real DefaultCamelCatalog (openai already has label ai in the catalog).
Cursor Agent on behalf of atiaomar1978-hub
Use catalog modelFromMavenGAV for mvn: GenAI detection instead of artifact-id heuristics, exclude camel-ai-observability from triggering duplicate observability deps, narrow AI_OBSERVABILITY_ENABLED visibility, and document camel.aiObservability known-deps entry. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Addressed all @gnodet review comments in
All 9 Cursor Agent on behalf of atiaomar1978-hub |
Summary
Auto-generated by Cursor Agent on behalf of atiaomar1978-hub
Implements CAMEL-24566: Camel JBang auto-discovers GenAI-related dependencies when running or exporting routes.
Approach
GenAI component and LangChain4j provider JARs are resolved by the existing silent-run pipeline (
DependencyDownloaderComponentResolver,KnownDependenciesResolver) — not by scanning route source.GenAiDependencyHelperonly adds optionalcamel:ai-observabilityusing the same settings-driven approach as OpenTelemetry and LRA.Changes
GenAiDependencyHelper— addscamel:ai-observabilitywhen GenAI artifacts are already in the dependency set and--observeorcamel.aiObservability.enabled=trueRun.java/ExportBaseCommand— call helper after silent-run dependency resolutioncamel-main-known-dependencies.properties— LangChain4j provider mappings +GenAiObservabilityImpl/camel.aiObservabilityentries for runtime downloadBehavior
camel:<scheme>mvn:dev.langchain4j:langchain4j-*:…--observeorcamel.aiObservability.enabled=truecamel:ai-observability(catalog ≥ 4.23)camel.aiObservability.enabled=falseopts out. Observability is not added without--observeor an explicit property.Review fixes (054c4fd)
mvn:GenAI detection — usesCamelCatalog.modelFromMavenGAV()+ catalogailabel instead of artifact-id string heuristicscamel-ai-observabilityexclusion — explicit observability dep no longer counts as a GenAI route dependency or gets duplicated inRun.java'sArrayListAI_OBSERVABILITY_ENABLED— narrowed to package-privatecamel.aiObservabilityknown-deps entry — documented (same pattern ascamel.opentelemetry)DefaultCamelCataloginstead of Mockito; duplicate-guard coverage addedTests
GenAiDependencyHelperTest— 9 unit testsExportTest.shouldExportGenAiRouteWithObservability— export integration with--observeRelated