CAMEL-24566: Auto-discover GenAI dependencies in Camel CLI - #26055
CAMEL-24566: Auto-discover GenAI dependencies in Camel CLI#26055atiaomar1978-hub wants to merge 4 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.
| 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?
| 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.
| * </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.
| 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.
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.
Changes
GenAiDependencyDiscovery— scans YAML, XML, and Java route sources for GenAI component URIs and LangChain4j provider packagesRun.java— adds discovered dependencies before launchExportBaseCommand.resolveDependencies()— same discovery for export,dependency list, anddependency update --scan-routescamel-main-known-dependencies.properties— package-level LangChain4j provider class-to-JAR mappings for runtime downloadBehavior
langchain4j-chat:,openai:, etc.)camel:<scheme>mvn:dev.langchain4j:langchain4j-ollama:…etc.--observeorcamel.aiObservability.enabled=truecamel:ai-observability(catalog ≥ 4.23)camel.aiObservability.enabled=falseopts out. Observability is not added by default without--observeor an explicit property.Tests
GenAiDependencyDiscoveryTest— 15 unit tests including false-positive guards and opt-in observabilityExportTest.shouldExportGenAiRouteWithObservability— export integration with--observeRelated