CAMEL-24339: Add llm scheme alias for OpenAI-compatible component - #26606
atiaomar1978-hub wants to merge 15 commits into
Conversation
Register llm as the primary URI scheme for camel-openai with openai as a backward-compatible alias. Update documentation, catalog metadata, Java/Component DSL builders, and add OpenAISchemeAliasTest covering independent component instances and chat completion for both schemes. Co-authored-by: Cursor Agent <noreply@cursor.com>
- Fix component doc feature list (remove unsupported operations) - Add llm.json website examples file - Document Endpoint DSL migration in 4.23 upgrade guide - Regenerate catalog documentation Co-authored-by: Cursor Agent <noreply@cursor.com>
Resolve merge conflicts keeping llm scheme alias changes while integrating latest main (GenAI observability, OpenAI new operations, OPA component DSL). Co-authored-by: Cursor Agent <noreply@cursor.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
The approach is correct — @Component("llm,openai") + @UriEndpoint(scheme = "llm,openai") is the standard Camel pattern for scheme aliases. The generated metadata, service-loader entries, and DSL artifacts look consistent. One binary-incompatible API removal needs to be fixed before this can merge.
Binary-incompatible removal (must fix):
EndpointHeaderBuilders.openai()(static method) was outright deleted — any code calling it getsNoSuchMethodErrorat runtime. Keep it as a deprecated delegate tollm():
/** @deprecated Use {@link #llm()} instead. */
@Deprecated
public static OpenAIEndpointBuilderFactory.OpenAIHeaderNameBuilder openai() {
return llm();
}default OpenAIHeaderNameBuilder openai()in theOpenAIBuildersinterface insideOpenAIEndpointBuilderFactorywas renamed tollm()— any code calling.openai()on a DSL route builder now fails to compile. Keep the old method as a deprecated default:
/** @deprecated Use {@link #llm()} instead. */
@Deprecated
default OpenAIHeaderNameBuilder openai() {
return llm();
}Both are generated files — the fix belongs in the code-generator template/config, not hand-edited here.
Minor (non-blocking):
-
openai-component.adocstill has:doctitle: OpenAIand:shortname: openaiwhile the primary scheme is nowllm. Consider:doctitle: LLM (OpenAI-compatible)and:shortname: llm. The filenameopenai-component.adoccan stay for backward compat of external links. -
OpenAISchemeAliasTest.bothSchemesCreateChatCompletionEndpoints()assertsopenaiEndpoint.getComponent().getDefaultName() == "llm". This is correct (DefaultComponent.doBuild()always returns the first scheme in@Component("llm,openai")), but surprising — any user who callscontext.getComponent("openai").getDefaultName()expecting"openai"gets"llm". Add a brief inline comment in the test so it reads as intentional. This asymmetry should also be mentioned in the upgrade guide (the entry was added but does not call this out).
This review was generated by an AI agent, Hermès on behalf of @gnodet.
Add deprecated alias delegates in endpoint DSL generator templates so EndpointHeaderBuilders.openai() and OpenAIBuilders.openai() delegate to llm() for binary compatibility. Update docs, upgrade guide, and test comment per review feedback. Co-authored-by: Omar Atie <atiaomar1978-hub@users.noreply.github.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review of commit c1ecdcf — previous findings #1 and #2 (binary-incompatible removals of EndpointHeaderBuilders.openai() and OpenAIBuilders.openai()) are fixed. New blocker found from the generated file, plus two smaller issues.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
…eprecation Regenerate llm.json with full OpenAI configuration metadata so the Endpoint DSL retains all builder methods (timeouts, image options, background, etc.). Mark alias scheme path builders @deprecated in the velocity templates and StaticEndpointBuilders.openai(), and clarify upgrade guide wording. Co-authored-by: Omar Atie <atiaomar1978-hub@users.noreply.github.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review of commit 43bc144 — two nits from review #2 are fixed: StaticEndpointBuilders.openai(String path) now has @Deprecated, and the upgrade guide no longer says "replaced by" (it correctly says "deprecated in favour of"). The main blocker from review #2 (incomplete Endpoint DSL regeneration) is not yet fixed, and this commit introduces a new binary-incompatible removal in the same category as review #1's original findings.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
Keep deprecated openai(String componentName, String path) bridges in the OpenAI Endpoint DSL and StaticEndpointBuilders, delegating to llm(), and update velocity templates so alias schemes generate both one- and two-arg deprecated delegates. Co-authored-by: Omar Atie <atiaomar1978-hub@users.noreply.github.com>
c00fff2 to
26357f0
Compare
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review of commit 26357f0 — all findings from previous reviews are resolved.
Previous blockers — status:
- ✅ Review #1: Binary-incompatible deletion of
EndpointHeaderBuilders.openai()andOpenAIBuilders.openai()— fixed - ✅ Review #2: Incomplete Endpoint DSL regeneration (28+ missing fluent builder methods) — fixed; full regeneration now present
- ✅ Review #2 nit:
StaticEndpointBuilders.openai(String path)missing@Deprecated— fixed - ✅ Review #2 nit: Upgrade guide wording ("replaced by" → "deprecated in favour of") — fixed
- ✅ Review #3: Two-arg
openai(String componentName, String path)removed without deprecated bridge fromOpenAIBuildersinterface — fixed - ✅ Review #3: Two-arg
openai(String componentName, String path)removed without deprecated bridge fromStaticEndpointBuilders— fixed - ✅ Review #1 nit: Add explanatory comment in test about
getDefaultName()asymmetry — fixed (// getDefaultName() returns the first scheme in @Component("llm,openai"), not the URI scheme used) - ✅ Review #1 nit: Document
getDefaultName()asymmetry in upgrade guide — fixed - ✅ Review #1 nit:
openai-component.adoc:doctitle:/:shortname:updated tollm— fixed
New in this commit:
The velocity template changes (endpoint-builder.vm, endpoint-static-builders.vm, endpoint-headers-builders.vm) now retrofit deprecated two-arg bridges for all scheme aliases in the codebase, not just openai. This is correct — it makes the code generator consistent for any component with multiple scheme aliases. The generated StaticEndpointBuilders.java diff confirms the pattern is applied uniformly (coaps, cometds, https, imaps/pop3/smtp aliases, smpps, etc.).
OpenAISchemeAliasTest is a solid addition — it verifies component resolution, independent instance configuration, and parameterized route execution with both schemes.
The PR is ready to merge.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
oscerd
left a comment
There was a problem hiding this comment.
Thanks for this — the llm/openai slice itself is nicely done: both llm.json and openai.json are produced and consistent (alternativeSchemes: "llm,openai", same options, javaType OpenAIComponent), OpenAIEndpointUriFactory lists both schemes, openai: stays fully working, the upgrade-guide note for openai() → llm() is in the right place, and OpenAISchemeAliasTest covers both schemes resolving to the same component. The Phase-1 "alias only" intent for camel-openai is exactly right.
The blocker is a side effect in the shared code-generation templates rather than anything wrong with the openai feature itself.
1. The velocity-template change deprecates legitimate peer schemes across the whole project (blocking). The three templates (endpoint-builder.vm, endpoint-headers-builders.vm, endpoint-static-builders.vm) are correctly guarded so single-scheme components are untouched — but they apply a positional "first scheme is canonical, every other scheme is a deprecated alias" rule to all multi-scheme components. In the regenerated aggregate builders this marks methods for other components @Deprecated:
EndpointHeaderBuilders.java/StaticEndpointBuilders.java:https()(http),imaps()/pop3()/pop3s()/smtp()/smtps()(mail),coaps()/coapTcp()(coap),cometds()(cometd),smpps()(smpp) all become@Deprecated, plus new(componentName, path)overloads.
Those are distinct protocols/schemes, not deprecated aliases of http/imap/coap/etc., so this would spray deprecation warnings across many existing routes. The "first canonical, rest deprecated" semantics is correct for openai → llm, but it needs to be opt-in / metadata-driven (mark the specific alias scheme deprecated) rather than derived positionally by scheme order for every multi-scheme component. This is also outside the stated Phase-1 scope ("scheme alias only, no other changes"). Worth aligning with @davsclaus on the mechanism, since he guided the Phase-1 approach on the JIRA.
2. Incomplete regeneration — CI's generated-sources check will fail (blocking). Because the templates now change output for every multi-scheme component, those components' per-component *EndpointBuilderFactory.java must be regenerated too. The diff only includes OpenAIEndpointBuilderFactory.java; MailEndpointBuilderFactory, CoAPEndpointBuilderFactory, HttpEndpointBuilderFactory, CometdEndpointBuilderFactory, SmppEndpointBuilderFactory (all visibly changing in the regenerated StaticEndpointBuilders.java) are not. A clean mvn install under dsl/camel-endpointdsl would rewrite them and leave the tree dirty, which Camel's build fails on. (CI hasn't reported yet — the fork branch is presumably awaiting maintainer workflow approval — so this is reasoned from the diff, not observed. Locally: build dsl/camel-endpointdsl and git status --porcelain src/generated.)
Minor: OpenAISchemeAliasTest uses JUnit assertions; the project prefers AssertJ for new test code (non-blocking).
Suggested path: keep the openai/llm changes, but make the alias-deprecation opt-in so only openai (not https/imaps/smtps/…) is marked deprecated, then regenerate and commit all affected modules. Happy to re-review once the template scoping is settled — the feature part is in good shape.
This is a rules-and-conventions review and does not replace specialized AI review tools or static analysis.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of oscerd
gnodet-bot
left a comment
There was a problem hiding this comment.
Follow-up on the @oscerd review (same commit 26357f0)
Both blocking findings in @oscerd's review are correct — and they were missed in my earlier APPROVE. I want to acknowledge them explicitly for the PR author.
Finding #1 — Confirmed. The velocity templates apply a positional "first scheme = canonical, rest = deprecated alias" rule to all multi-scheme components. Verified locally against upstream/main:
The following methods in StaticEndpointBuilders.java (and the corresponding CoAPBuilders/MailBuilders/etc. interfaces in per-component factory files) are not deprecated on main but gain @Deprecated in this PR as a side-effect:
coapTcp, coaps, coapsTcp, cometds, https, imaps, pop3, pop3s, smpps, smtp, smtps
These are distinct protocols/schemes, not deprecated aliases of imap/coap/http. The deprecation is unintended and would cause widespread @Deprecated warnings in user code. The template logic needs to be opt-in (e.g., driven by a flag in the component model rather than positional scheme order).
Finding #2 — Confirmed. Because the template change affects every multi-scheme component's per-component factory interface (the ${ComponentName}Builders inner interface in *EndpointBuilderFactory.java), files like CoAPEndpointBuilderFactory.java, MailEndpointBuilderFactory.java, HttpEndpointBuilderFactory.java, CometdEndpointBuilderFactory.java, and SmppEndpointBuilderFactory.java would be modified by a regeneration run. They are absent from the diff, which means a clean mvn install on dsl/camel-endpointdsl would leave the tree dirty and the generated-sources check would fail.
Suggested path (aligns with @oscerd's recommendation): Keep the llm/openai changes (they are correct). Scope the deprecation so it applies only when the component model explicitly marks a scheme as a deprecated alias (e.g., via a metadata field), rather than deriving it positionally. This avoids touching CoAP, Mail, HTTP, etc., and keeps the template change's blast radius to zero for existing components.
This comment was generated by an AI agent, Hermes — these findings were missed in the prior review and I'm correcting the record.
…edSchemes Add @UriEndpoint.deprecatedSchemes metadata so only explicitly marked alias schemes (openai for llm) are @deprecated in generated Endpoint DSL builders. This fixes the review finding that positional alias deprecation incorrectly marked peer schemes such as https, coaps, and imaps as deprecated across all multi-scheme components. Regenerate OpenAI catalog metadata and aggregate Endpoint DSL builders. Migrate OpenAISchemeAliasTest to AssertJ. Co-authored-by: Cursor <cursoragent@cursor.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review of commit 04d5349 — both blockers from @oscerd's review are resolved. One new issue found in the new commit.
Previous blockers — status:
- ✅ oscerd #1: Velocity templates apply
@Deprecatedto all multi-scheme components positionally — fixed.isDeprecatedSchemeAlias()is now opt-in, driven by thedeprecatedSchemesmetadata field.StaticEndpointBuilders.javaandEndpointHeaderBuilders.javano longer carry spurious@Deprecatedoncoaps,https,imaps,cometds, etc. - ✅ oscerd #2: Incomplete regeneration (per-component factory files missing) — fixed. The template change is now scoped to
llm/openaionly via the opt-in mechanism, so no other*EndpointBuilderFactory.javafiles need regeneration. The aggregate builders are correctly updated.
New blocker (introduced in this commit):
In EndpointSchemaGeneratorMojo.findComponentProperties(), model.setDeprecatedSchemes(...) is called unconditionally for every scheme derived from the @UriEndpoint annotation — including the alias scheme. This means openai.json gets:
"scheme": "openai",
"deprecatedSchemes": "openai"The alias scheme is listing itself as deprecated. The DSL generator is safe because isDeprecatedSchemeAlias() has a self-reference guard (master.getScheme().equals(alias.getScheme())), but catalog consumers reading the JSON directly (IDEs, Camel catalog tools, camel-jbang completion) will see a misleading deprecatedSchemes field on the openai entry.
The fix is to only set deprecatedSchemes when the current scheme is the primary (non-deprecated) scheme — i.e., skip it when scheme itself appears in uriEndpoint.deprecatedSchemes():
// Only attach deprecatedSchemes to the primary (non-deprecated) scheme entry
if (!Strings.isNullOrEmpty(uriEndpoint.deprecatedSchemes())
&& !Arrays.asList(uriEndpoint.deprecatedSchemes().split(",")).contains(scheme)) {
model.setDeprecatedSchemes(uriEndpoint.deprecatedSchemes());
}After this fix, openai.json will not carry deprecatedSchemes (it has nothing to declare deprecated from its own perspective), and llm.json will correctly carry "deprecatedSchemes": "openai".
This review was generated by an AI agent, Hermès on behalf of @gnodet.
…entry Skip deprecatedSchemes metadata on alias scheme JSON entries so openai.json no longer declares itself deprecated. Regenerate openai catalog metadata and add a unit test for the opt-in behavior. Co-authored-by: Omar Atie <atiaomar1978-hub@users.noreply.github.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review of commit f276680 — the applyDeprecatedSchemes fix (last blocker from review #6) is correct: llm.json carries "deprecatedSchemes": "openai" and openai.json does not. However, a new compile blocker has appeared due to the merge-from-main commit (861fd3f) not capturing a subsequent main change.
New blocker — stale generated files referencing a deleted class (compile failure):
The camel-hazelcast-atomicvalue component was removed from the main branch in commit b8debda9a865 (merged 2026-09-15, after this PR's merge-from-main commit). The template changes in this PR regenerated EndpointHeaderBuilders.java and StaticEndpointBuilders.java based on a Camel state that still included HazelcastAtomicnumberEndpointBuilderFactory — but that class no longer exists. The generated files in the current PR HEAD contain:
// EndpointHeaderBuilders.java
public static HazelcastAtomicnumberEndpointBuilderFactory.HazelcastAtomicnumberHeaderNameBuilder hazelcastAtomicvalue() {
return HazelcastAtomicnumberEndpointBuilderFactory.HazelcastAtomicnumberHeaderNameBuilder.INSTANCE;
}
// StaticEndpointBuilders.java
public static HazelcastAtomicnumberEndpointBuilderFactory.HazelcastAtomicnumberEndpointBuilder hazelcastAtomicvalue(String path) { ... }
public static HazelcastAtomicnumberEndpointBuilderFactory.HazelcastAtomicnumberEndpointBuilder hazelcastAtomicvalue(String componentName, String path) { ... }HazelcastAtomicnumberEndpointBuilderFactory does not exist in current main. This will produce a compile error in dsl/camel-endpointdsl.
Fix: rebase this branch on the current main (or git merge upstream/main), then re-run the code generator:
./mvnw -pl dsl/camel-endpointdsl generate-sources -Dfastinstall
Commit the updated generated files. The hazelcastAtomicvalue stubs should disappear because HazelcastAtomicnumberEndpointBuilderFactory is no longer in scope for the generator.
Minor nit (non-blocking):
OpenAIBuilders.openai(String path) in OpenAIEndpointBuilderFactory still calls return OpenAIEndpointBuilderFactory.endpointBuilder("openai", path) directly, while StaticEndpointBuilders.openai(String path) was updated to delegate through llm("openai", path). Both produce the same runtime result, but the inconsistency may confuse future readers. Consider making the interface method consistent:
@Deprecated
default OpenAIEndpointBuilder openai(String path) {
return llm("openai", path);
}This review was generated by an AI agent, Hermès on behalf of @gnodet.
Co-authored-by: Omar Atie <atiaomar1978-hub@users.noreply.github.com>
Merge upstream/main to pick up removal of camel-hazelcast-atomicvalue.
Regenerate endpoint DSL so aggregate builders no longer reference the
deleted HazelcastAtomicnumberEndpointBuilderFactory class.
Make deprecated alias path methods in OpenAIBuilders delegate through
the primary scheme method (llm("openai", path)) for consistency with
StaticEndpointBuilders.
Co-authored-by: Cursor <cursoragent@cursor.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review of commit 5d13d82 — the compile blocker from review #8 (stale HazelcastAtomicnumberEndpointBuilderFactory references in EndpointHeaderBuilders.java and StaticEndpointBuilders.java) is fixed. All previous findings are fully resolved.
Previous blockers — status:
- ✅ Review #1: Binary-incompatible deletion of
EndpointHeaderBuilders.openai()andOpenAIBuilders.openai()— fixed - ✅ Review #2: Incomplete Endpoint DSL regeneration (28+ missing fluent builder methods) — fixed
- ✅ Review #2 nit:
StaticEndpointBuilders.openai(String path)missing@Deprecated— fixed - ✅ Review #2 nit: Upgrade guide wording ("replaced by" → "deprecated in favour of") — fixed
- ✅ Review #3: Two-arg
openai(String componentName, String path)bridges missing — fixed - ✅ oscerd #1 / Review #4: Velocity templates marking all multi-scheme components deprecated positionally — fixed via opt-in
deprecatedSchemesmetadata field - ✅ oscerd #2 / Review #4: Incomplete regeneration of per-component factory files — fixed (scope now only affects openai via opt-in)
- ✅ Review #5:
openai.jsoncarrying"deprecatedSchemes": "openai"(self-reference) — fixed byapplyDeprecatedSchemes()guard - ✅ Review #6:
EndpointSchemaGeneratorMojoattachingdeprecatedSchemesto alias scheme entries — fixed - ✅ Review #7 nit:
openai(String path)inOpenAIBuildersinterface delegating throughendpointBuilder("openai", path)instead ofllm("openai", path)— fixed - ✅ Review #8: Stale
hazelcastAtomicvalue()methods referencing deletedHazelcastAtomicnumberEndpointBuilderFactory— fixed by rebase + regeneration
Current state is correct:
UriEndpoint.deprecatedSchemesis a proper opt-in annotation field with JavadocEndpointDslMojo.isDeprecatedSchemeAlias()has a self-reference guard (master.getScheme().equals(alias.getScheme())→ false)applyDeprecatedSchemes()is unit-tested viaEndpointSchemaGeneratorMojoTest.shouldAttachDeprecatedSchemesOnlyToPrimarySchemeEntry()EndpointHeaderBuilders,StaticEndpointBuilders, andOpenAIEndpointBuilderFactoryall carry correct@Deprecatedbridges with delegation to thellm()variantsopenai.jsoncorrectly has nodeprecatedSchemesfield;llm.jsoncarries"deprecatedSchemes": "openai"OpenAISchemeAliasTestuses AssertJ and covers independent component configuration- No spurious
@Deprecatedonhttps,imaps,coaps,cometds,smpps, or other peer schemes
The PR is ready to merge.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
davsclaus
left a comment
There was a problem hiding this comment.
Thanks for sticking with this through the review rounds - the llm/openai slice itself works, OpenAISchemeAliasTest covers what matters, and CI got through the whole reactor (all modules, all tests) before stopping at docs:xref-check. Three things to sort out, one of them a scope question I would like to settle before you spend more time on the generator.
1. CI failure: one broken xref. Reproduced locally with mvn camel-package-maven-plugin:xref-check in docs/: the upgrade guide uses xref:components:openai-component.adoc and needs the double colon (components::). Suggestion inline.
2. Scope: the PR now deprecates the openai scheme, which was not part of Phase 1. The plan on CAMEL-24339 was "scheme alias only - openai stays as a working alias". What landed here instead is deprecatedSchemes = "openai" and, to support it, a new public SPI attribute on @UriEndpoint (in tooling/spi-annotations plus the generated camel-api copy), a new deprecatedSchemes field in ComponentModel and the catalog JSON, changes to three velocity templates, mojo logic and a mojo test. I can see how it got there: the first commit dropped the generated openai() helpers, the review asked for deprecated bridges, the templates then over-applied deprecation to https/imaps/coaps (oscerd's catch), so an opt-in flag was added, and so on. But main already handles multi-scheme components (http,https, imap,imaps,pop3,...) with zero tooling changes: every scheme gets its own JSON, service file and xxx(String path) DSL method, none of them deprecated. Deprecating a scheme that has shipped in two LTS lines is a decision for the dev list, not something a generator flag should carry, and a new @UriEndpoint attribute plus a catalog field is a lot of public surface for one component.
So please drop the tooling/SPI part entirely: revert UriEndpoint (both copies), ComponentModel, JsonMapper, EndpointDslMojo, EndpointSchemaGeneratorMojo and its test, SomeAliasEndpoint, and the three .vm templates, remove deprecatedSchemes from OpenAIEndpoint, and regenerate. The only DSL difference left is the header-name builder (EndpointHeaderBuilders.openai() / OpenAIBuilders.openai()), which the generator emits for the first scheme only. The simplest way to keep that stable is to order the schemes @Component("openai,llm") / @UriEndpoint(scheme = "openai,llm", title = "OpenAI,LLM", syntax = "openai:operation"): llm: works exactly the same, llm.json still appears in the catalog (with syntax: llm:operation, since the generator substitutes the alias), the doc title can still lead with LLM, and nothing existing changes - which is what "alias only" means. With that the PR shrinks to the two annotations, the generated files, the doc and the upgrade-guide note (which can then drop the paragraphs about deprecated helpers and getDefaultName()).
3. Doc heading. openai-component.adoc still starts with = OpenAI Component while :doctitle: is now LLM; the two should agree.
Claude Code on behalf of @davsclaus
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
| `Component.getDefaultName()` returns the first scheme declared in `@Component("llm,openai")` | ||
| (`"llm"`) for both `llm` and `openai` component instances. | ||
|
|
||
| See xref:components:openai-component.adoc[LLM Component] for details. |
There was a problem hiding this comment.
This is the xref that fails xref-check on CI - the components module needs the double colon.
| See xref:components:openai-component.adoc[LLM Component] for details. | |
| See xref:components::openai-component.adoc[LLM Component] for details. |
| * {@code @Deprecated} in the Endpoint DSL. Peer schemes such as {@code http}/{@code https} or {@code coap}/ | ||
| * {@code coaps} must not be listed here. | ||
| */ | ||
| String deprecatedSchemes() default ""; |
There was a problem hiding this comment.
This is a public SPI annotation used by every component and by external tooling, so a new attribute here is a permanent API. For a Phase 1 alias it should not be needed at all - see the review body: ordering the schemes openai,llm keeps every existing generated helper intact without any generator change.
| title = "OpenAI", | ||
| syntax = "openai:operation", | ||
| scheme = "llm,openai", | ||
| deprecatedSchemes = "openai", |
There was a problem hiding this comment.
Deprecating the openai scheme was not part of the Phase 1 agreement on CAMEL-24339 ("openai stays as a working alias"). Please drop this; if we ever want to deprecate the scheme that should be a separate dev-list decision.
| @@ -1,8 +1,8 @@ | |||
| = OpenAI Component | |||
There was a problem hiding this comment.
The heading still says OpenAI Component while :doctitle: below is LLM - they should match, e.g. = LLM Component.
Drop deprecatedSchemes SPI/tooling and revert velocity templates to main. Order schemes openai,llm so existing DSL helpers stay stable without deprecating openai. Fix upgrade guide xref (components::), simplify alias section, and align doc heading with LLM doctitle. Co-authored-by: Omar Atie <atiaomar1978-hub@users.noreply.github.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review of commit 828bbd5 — all three blockers from @davsclaus's review are resolved.
Previous blockers — status:
- ✅ davsclaus #1: CI failure — broken xref in upgrade guide (
xref:components::openai-component.adocdouble-colon) — fixed. - ✅ davsclaus #2: Scope creep —
deprecatedSchemesSPI attribute,ComponentModel,JsonMapper, generator mojo changes, velocity template patches — all reverted. The diff is now exactly what Phase 1 requires: two annotation changes (@Component,@UriEndpoint), generated files, docs. - ✅ davsclaus #2 (sub-issue): scheme ordering —
@UriEndpoint(scheme = "openai,llm")withopenaias primary keeps all existingopenai()DSL helpers untouched and non-deprecated. - ✅ davsclaus #3: Doc heading —
= LLM Componentmatches:doctitle: LLM.
Current state:
@Component("openai,llm")/@UriEndpoint(scheme = "openai,llm", title = "LLM,OpenAI", syntax = "openai:operation")— correct Phase 1 alias-only implementation.- Generated service-loader entries, catalog JSONs (
llm.json, updatedopenai.json), component/endpoint DSL (llm()builders), andcore/camel-mainproperties are consistent. openai()methods inEndpointHeaderBuilders,StaticEndpointBuilders, andOpenAIEndpointBuilderFactory.OpenAIBuildersare unchanged and not deprecated — binary compatible.- New
llm(String path)convenience methods added inStaticEndpointBuildersandOpenAIBuilders— functional. OpenAISchemeAliasTestcovers independent component instances and scheme resolution.- Upgrade guide entry is accurate and the xref syntax is correct.
One observation (non-blocking): StaticEndpointBuilders.llm(String componentName, String path) and OpenAIBuilders.llm(String componentName, String path) two-arg overloads are absent — the existing openai() methods have all three overloads (openai(), openai(String path), openai(String componentName, String path)). For full parity the two-arg llm variants should be added. That said, llm(String path) delegates to openai("llm", path) so the functionality is there; the two-arg form is only needed if a caller wants to override the component name, which is an edge case. I'd leave this to the maintainers' discretion — not a blocker.
PR is solid. No unresolved blockers.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
Resolve OpenAIEndpointBuilderFactory conflict by regenerating endpoint DSL after merging upstream main (batch API and other openai changes). Co-authored-by: Omar Atie <atiaomar1978-hub@users.noreply.github.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review of commit dfc2c08 — the merge from main (ee626c6) integrated a large batch of new camel-openai features (batch API, webhook consumer, multimodal support, new operations). The llm alias DSL methods were hand-added before those upstream changes landed, and the merge resolution did not regenerate them with the new operation set. Three concrete gaps:
Previous findings — status:
- ✅ davsclaus #1: xref-check CI failure — fixed in 828bbd5
- ✅ davsclaus #2:
deprecatedSchemesscope creep — fixed in 828bbd5 - ✅ davsclaus #3:
@Deprecatedonopenai— dropped in 828bbd5
This review was generated by an AI agent, Hermès on behalf of @gnodet.
| return OpenAIEndpointBuilderFactory.endpointBuilder(componentName, path); | ||
| } | ||
| /** | ||
| * OpenAI (camel-openai) |
There was a problem hiding this comment.
"OpenAI (camel-openai)" should be "LLM (camel-openai)"
All other llm() Javadoc blocks in this file use "LLM (camel-openai)" (e.g. line 6990, 7005, 7036). This one was copied from the openai() block and the title was not updated.
| * OpenAI (camel-openai) | |
| /** | |
| * LLM (camel-openai) |
| * 'responses-retrieve', 'responses-cancel', 'embeddings', | ||
| * 'tool-execution', 'audio-transcription', 'audio-translation', | ||
| * 'audio-speech', 'moderation', 'image-generation', or 'image-edit' | ||
| * There are 12 enums and the value can be one of: chat-completion, | ||
| * responses, responses-retrieve, responses-cancel, embeddings, | ||
| * tool-execution, audio-transcription, audio-translation, audio-speech, | ||
| * moderation, image-generation, image-edit |
There was a problem hiding this comment.
llm() operation list is stale — missing the 5 operations added in the main merge
The openai(String path) method above (line 7023) lists 17 operations including batch, batch-retrieve, batch-cancel, batch-results, and webhook. The llm() method here still lists only 12 (the pre-merge set). Since llm: is a full alias for the same endpoint, both schemes support all the same operations — the Javadoc should match.
This was introduced by the merge resolution: llm() was hand-added at commit 828bbd5 before the batch/webhook operations landed on main. The regeneration step in the merge commit did not update the llm() overloads.
Fix: regenerate the endpoint DSL after rebasing onto current main.
| */ | ||
| default OpenAIEndpointBuilder llm(String path) { | ||
| return OpenAIEndpointBuilderFactory.endpointBuilder("llm", path); | ||
| } |
There was a problem hiding this comment.
llm(String componentName, String path) two-arg overload
openai(String componentName, String path) exists at line 7065. The llm() entry directly below has only the single-arg form. The two-arg overload is the standard way to register a custom component bean under a given scheme; omitting it for llm while providing it for openai is an asymmetry that will confuse users who switch from openai to llm.
This can be added manually or fixed by running the DSL generator, which should produce it automatically once the llm scheme is registered.
| return LdifEndpointBuilderFactory.endpointBuilder(componentName, path); | ||
| } | ||
| /** | ||
| * OpenAI (camel-openai) |
There was a problem hiding this comment.
"OpenAI (camel-openai)" should be "LLM (camel-openai)"
The block starting at this line describes the llm(String path) method added below. The title was not updated from the generated template.
| * OpenAI (camel-openai) | |
| /** | |
| * LLM (camel-openai) |
| */ | ||
| public static OpenAIEndpointBuilderFactory.OpenAIEndpointBuilder llm(String path) { | ||
| return openai("llm", path); | ||
| } |
There was a problem hiding this comment.
llm(String componentName, String path) two-arg static overload + stale operation list
The openai(String componentName, String path) overload exists in this class. llm needs the same. Additionally, the operation list in the llm(String path) Javadoc above lists 12 operations — the pre-merge set — while openai(String path) now lists 17. Both should be regenerated.
Note: llm(String path) delegates to openai("llm", path) — the two-arg llm overload should simply be:
public static OpenAIEndpointBuilderFactory.OpenAIEndpointBuilder llm(String componentName, String path) {
return openai(componentName, path);
}| * OpenAI-compatible APIs. The openai scheme is a supported alias. | ||
| * | ||
| * Category: ai | ||
| * Since: 4.17 |
There was a problem hiding this comment.
llm() header builder alias
This class provides openai() → OpenAIHeaderNameBuilder.INSTANCE. Users who write their routes using the llm: scheme and the fluent header DSL will look for llm() here, not openai(). Since the header constants are scheme-agnostic, the fix is a one-liner alias:
/**
* LLM (camel-openai)
* LLM endpoint for chat completion, Responses API, embeddings, audio
* transcription, audio translation, and text-to-speech using
* OpenAI-compatible APIs. The openai scheme is a supported alias.
*
* @return the dsl builder for the headers' name.
*/
@Deprecated
public static OpenAIEndpointBuilderFactory.OpenAIHeaderNameBuilder llm() {
return OpenAIEndpointBuilderFactory.OpenAIHeaderNameBuilder.INSTANCE;
}(The @Deprecated is not required here — openai() itself is not deprecated — this is just for discoverability. Drop the annotation if the intent is parity with openai() which is also non-deprecated.)
Fix stale llm() Javadoc and operation list after merging upstream camel-openai changes (batch API, webhook consumer). Set @UriEndpoint title to "LLM" so generated catalog and DSL use the correct component name. Co-authored-by: Omar Atie <atiaomar1978-hub@users.noreply.github.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review of commit 4c9cce7 — three gaps from review #9 are partially addressed (Javadoc titles and operation lists are now correct), but the three missing method overloads from review #9 are still absent, and a new title-convention regression was introduced.
Previous findings — status:
- ✅ Review #9 gap: Wrong Javadoc title
"OpenAI (camel-openai)"onllm(String path)inOpenAIEndpointBuilderFactory— fixed - ✅ Review #9 gap:
llm()operation list stale (12 ops instead of 17) inOpenAIEndpointBuilderFactory— fixed (now lists all 17) - ✅ Review #9 gap: Wrong Javadoc title on
llm(String path)inStaticEndpointBuilders— fixed - ✅ Review #9 gap: Stale operation list in
StaticEndpointBuilders.llm()Javadoc — fixed (17 ops) - ❌ Review #9 gap:
llm(String componentName, String path)missing fromOpenAIBuildersinterface — still not fixed - ❌ Review #9 gap:
llm(String componentName, String path)missing fromStaticEndpointBuilders— still not fixed - ❌ Review #9 gap:
llm()header builder alias missing fromEndpointHeaderBuilders— still not fixed
New regression in this commit:
@UriEndpoint(title = "LLM") with scheme = "openai,llm" violates the multi-scheme title convention. Camel's code generator maps titles positionally: title[i] → scheme[i].json. With a single title "LLM", the generator sets openai.json title to "LLM" — which is what the diff confirms (-"title": "OpenAI" → +"title": "LLM" in openai.json). Catalog consumers, IDE tooling, and camel-jbang completions that look up the openai component by name now get "LLM" as its title instead of "OpenAI". This is a catalog regression for existing users of the openai scheme.
The correct value, following the http,https → HTTP,HTTPS and imap,imaps,... → IMAP,IMAPS,... convention, is title = "OpenAI,LLM" — that keeps openai.json titled "OpenAI" and gives llm.json the title "LLM".
This review was generated by an AI agent, Hermès on behalf of @gnodet.
| * LLM endpoint for chat completion, Responses API, embeddings, audio transcription, audio translation, and | ||
| * text-to-speech using OpenAI-compatible APIs. The {@code openai} scheme is a supported alias. | ||
| */ | ||
| @UriEndpoint(firstVersion = "4.17.0", |
There was a problem hiding this comment.
title = "LLM" breaks the multi-scheme title convention — catalog regression for openai users.
Camel's code generator maps titles to schemes positionally: scheme[i] → title[i]. With scheme = "openai,llm" and a single title = "LLM", the generator assigns "LLM" as the title for openai.json — confirmed by the diff (-"title": "OpenAI" → +"title": "LLM" in catalog/components/openai.json). Any catalog consumer, IDE plugin, or camel-jbang completion that looks up the openai component by name now sees "LLM" instead of "OpenAI".
The precedent is clear:
@UriEndpoint(scheme = "http,https", title = "HTTP,HTTPS")→http.jsontitle:HTTP,https.jsontitle:HTTPS (Secure)@UriEndpoint(scheme = "imap,imaps,pop3,pop3s,smtp,smtps", title = "IMAP,IMAPS,POP3,POP3S,SMTP,SMTPS")
Fix:
| @UriEndpoint(firstVersion = "4.17.0", | |
| scheme = "openai,llm", | |
| title = "OpenAI,LLM", |
Then regenerate so openai.json gets title "OpenAI" and llm.json gets title "LLM".
| * @return the dsl builder | ||
| */ | ||
| default OpenAIEndpointBuilder llm(String path) { | ||
| return OpenAIEndpointBuilderFactory.endpointBuilder("llm", path); |
There was a problem hiding this comment.
llm(String componentName, String path) two-arg overload still missing (raised in review #9).
openai(String componentName, String path) exists at line 7061 in this file. The llm entry has only the single-arg form. Users switching from openai to llm who use the two-arg form (needed when registering a custom component bean under the llm scheme name) will find no equivalent and must fall back to openai() — defeating the purpose of the alias.
Add immediately after the llm(String path) method:
/**
* LLM (camel-openai)
* LLM endpoint for chat completion, Responses API, embeddings, audio
* transcription, audio translation, and text-to-speech using
* OpenAI-compatible APIs. The openai scheme is a supported alias.
*
* @param componentName to use a custom component name for the endpoint instead of the default name
* @param path operation
* @return the dsl builder
*/
default OpenAIEndpointBuilder llm(String componentName, String path) {
return OpenAIEndpointBuilderFactory.endpointBuilder(componentName, path);
}| * @param path operation | ||
| * @return the dsl builder | ||
| */ | ||
| public static OpenAIEndpointBuilderFactory.OpenAIEndpointBuilder llm(String path) { |
There was a problem hiding this comment.
llm(String componentName, String path) static two-arg overload still missing (raised in review #9).
openai(String componentName, String path) exists in this class. The llm entry only has llm(String path). Add the two-arg static method:
/**
* LLM (camel-openai)
* LLM endpoint for chat completion, Responses API, embeddings, audio
* transcription, audio translation, and text-to-speech using
* OpenAI-compatible APIs. The openai scheme is a supported alias.
*
* @param componentName to use a custom component name for the endpoint instead of the default name
* @param path operation
* @return the dsl builder
*/
public static OpenAIEndpointBuilderFactory.OpenAIEndpointBuilder llm(String componentName, String path) {
return openai(componentName, path);
}| * OpenAI-compatible APIs. The openai scheme is a supported alias. | ||
| * | ||
| * Category: ai | ||
| * Since: 4.17 |
There was a problem hiding this comment.
llm() header builder alias still missing (raised in review #9).
This file exposes openai() → OpenAIHeaderNameBuilder.INSTANCE. Users writing routes with the llm: scheme and the fluent header DSL will look for llm() here. The method is a trivial one-liner. Add it directly after the openai() block:
/**
* LLM (camel-openai)
* LLM endpoint for chat completion, Responses API, embeddings, audio
* transcription, audio translation, and text-to-speech using
* OpenAI-compatible APIs. The openai scheme is a supported alias.
*
* Category: ai
* Since: 4.17
* Maven coordinates: org.apache.camel:camel-openai
*
* @return the dsl builder
*/
public static OpenAIEndpointBuilderFactory.OpenAIHeaderNameBuilder llm() {
return OpenAIEndpointBuilderFactory.OpenAIHeaderNameBuilder.INSTANCE;
}Use title = "OpenAI,LLM" so openai.json keeps title "OpenAI" and llm.json gets "LLM". Add missing llm() header builder and two-arg endpoint DSL overloads after the main merge. Restore openai-component.adoc heading to match the primary scheme convention. Co-authored-by: Cursor <cursoragent@cursor.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review of commit 3593534 — all four findings from review #10 are addressed. One open item from @davsclaus's review #10 is still pending.
Previous findings — status:
- ✅
title = "LLM"catalog regression (review #10) — fixed: nowtitle = "OpenAI,LLM", keepingopenai.jsontitled"OpenAI"andllm.jsontitled"LLM" - ✅
llm(String componentName, String path)missing fromOpenAIBuildersinterface (review #9) — fixed - ✅
llm(String componentName, String path)missing fromStaticEndpointBuilders(review #9) — fixed - ✅
llm()header builder alias missing fromEndpointHeaderBuilders(review #9) — fixed - ✅ Broken xref path in upgrade guide (
xref:components:→xref:components::) — fixed - ❌
openai-component.adocheading= OpenAI Component/:doctitle: OpenAIinconsistent with body text — still not fixed (see below)
Remaining open item: doc title/heading inconsistency
In components/camel-ai/camel-openai/src/main/docs/openai-component.adoc (and the generated catalog copy), the page heading and doctitle attribute still say "OpenAI" while the body has been updated to use "LLM component":
= OpenAI Component ← page heading, still says OpenAI
:doctitle: OpenAI ← doctitle attribute, still says OpenAI
...
The LLM component provides integration... ← body uses LLM
This is the inconsistency @davsclaus flagged in review #10 item 3. The = OpenAI Component heading is what appears in the rendered docs ToC and as the page <h1>. Given the component file is openai-component.adoc (and must stay that — it's the canonical file name), the correct fix is:
= LLM Component
:doctitle: LLM
The :shortname: and :artifactid: remain openai. The page renders as "LLM Component" while the file URL stays openai-component.adoc, which is consistent with the Phase-1 approach.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
Set page heading and :doctitle: to LLM while keeping :shortname: openai and openai.json catalog title unchanged per multi-scheme convention. Co-authored-by: Omar Atie <atiaomar1978-hub@users.noreply.github.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review of commit 745a0cc — the doc heading fix from review #11 is applied. All previous findings are fully resolved.
Previous finding — status:
- ✅ Review #11:
openai-component.adocheading= OpenAI Component/:doctitle: OpenAIinconsistent with body using LLM — fixed. Both the source file and the catalog copy now read= LLM Component/:doctitle: LLM, while:shortname: openaiis preserved for URL backward compatibility.
Current state:
@Component("openai,llm")/@UriEndpoint(scheme = "openai,llm", title = "OpenAI,LLM", syntax = "openai:operation")— correct Phase 1 alias-only implementation.openai.jsontitle stays"OpenAI",llm.jsontitle is"LLM"— catalog convention preserved.- All DSL builders (
openai(),openai(String path),openai(String componentName, String path)) unchanged and non-deprecated — binary compatible. - New
llm(),llm(String path),llm(String componentName, String path)builders inStaticEndpointBuilders,EndpointHeaderBuilders, andOpenAIBuilders— complete parity. OpenAIEndpointUriFactorylists both schemes for URI factory routing.- Service-loader entries (
META-INF/services/.../component/llm,configurer/llm-component,configurer/llm-endpoint) are present. OpenAISchemeAliasTestuses AssertJ, covers independent component configuration and both schemes.- Upgrade guide entry is accurate with correct
xref:components::openai-component.adocdouble-colon syntax.
The PR is ready to merge.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
Description
Adds
llmas the primary URI scheme for thecamel-openaicomponent, withopenairetained as a backward-compatible alias. This addresses discoverability concerns in CAMEL-24339: the component works with any OpenAI-compatible API (Ollama, vLLM, LM Studio, OpenRouter, Azure OpenAI, etc.), not OpenAI alone.Phase 1 approach (per JIRA discussion with @davsclaus): scheme alias only — no Maven artifact rename, no Java package rename, no header constant changes.
Changes
@Component("llm,openai")onOpenAIComponent@UriEndpoint(scheme = "llm,openai", title = "LLM,OpenAI", syntax = "llm:operation")onOpenAIEndpointllm.json, updatedopenai.json), component/endpoint DSL (llm()builders), and service loader entriesopenai-component.adoctitle/shortname → LLM) and AI summaryllm()migration, independentcamel.component.llm.*config)docs/components/modules/ROOT/examples/json/llm.jsonOpenAISchemeAliasTestcovering independent component instances and chat completion for both schemesBackward compatibility
openai:chat-completionroutes continue to work unchangedcamel-openaiCamelOpenAI*headers unchangedcamel.component.openai.*andcamel.component.llm.*configure separate component instancesllm()andopenai(); Endpoint DSL primary helper is nowllm()Testing
Target
mainbranch)Tracking
https://issues.apache.org/jira/browse/CAMEL-24339
Apache Camel coding standards and style
mvn clean install -DskipTestslocally from root folder and I have committed all auto-generated changes.AI-assisted contributions
Co-authored-bytrailers) and the PR description identifies the AI tool used.AI-generated PR description on behalf of atiaomar1978-hub (Cursor Agent)