[ 
https://issues.apache.org/jira/browse/CAMEL-24708?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18115698#comment-18115698
 ] 

Claus Ibsen commented on CAMEL-24708:
-------------------------------------

Design, after looking at the code:

*Exposure*: {{camel_catalog_doc kind=api}} (auto-detected: {{name=Exchange}} 
without a kind falls through after {{bean}}). No new tool. The kind description 
changes in CatalogDocs, both AuthoringTools (camel-jbang-core and 
camel-jbang-mcp) and camel-jbang-mcp.adoc.

*Source of the cards: {{@Metadata}} on the chosen methods in camel-api*, not a 
properties file. {{org.apache.camel.spi.Metadata}} already targets METHOD and 
has description, label, important and examples; Exchange.java already uses it 
on the header constants. camel-package-maven-plugin's {{generate}} goal runs on 
camel-api (core/pom.xml), builds the Jandex index and runs 
GeneratePojoBeanMojo, which selects {{@Metadata(label = "bean")}} from the 
index. A new GenerateApiReferenceMojo in the same invoke list selects {{label = 
"api"}}, gets the method name, parameters, return type and throws from Jandex 
(no Roaster, no source path), and writes 
{{src/generated/resources/META-INF/org/apache/camel/api/<Class>.json}} in 
camel-api. PrepareCatalogMojo copies them into camel-catalog under 
{{org/apache/camel/catalog/api/}} like it does for beans/. Drift is impossible 
by construction: a renamed or removed method takes its annotation with it, and 
the description is reviewed by whoever changes the method.

{code:java}
@Metadata(label = "api", description = "The bean registry: lookupByName(name), 
lookupByNameAndType(name, type)")
Registry getRegistry();

@Metadata(label = "api", description = "Creates a template to send to 
endpoints; create once and reuse, not per exchange",
          examples = { "context.createProducerTemplate().sendBody(\"direct:x\", 
body)" })
ProducerTemplate createProducerTemplate();
{code}

Annotate one overload per name; the mojo lists the sibling overloads from 
ClassInfo.methods(). The single-method interfaces (AggregationStrategy, 
Processor, Predicate, Expression) get the method plus a class-level 
{{@Metadata(label = "api", description = ...)}} carrying the common-mistakes 
text (AggregationStrategy: first call oldExchange is null, return newExchange). 
The "Camel 4 changes" block (no getOut(), getIn() is getMessage(), header 
constants) is a class-level annotation on Exchange.

*CamelContext card* (the important and very common methods only; the is* flags, 
management and lifecycle accessors are left out): getRegistry, 
getTypeConverter, getEndpoint, getRoute, getRoutes, getRouteController, 
createProducerTemplate, createFluentProducerTemplate, createConsumerTemplate, 
resolvePropertyPlaceholders, getPropertiesComponent, getVariable, 
resolveLanguage, resolveDataFormat, getComponent, getName, getVersion, 
getGlobalOption. Notes: context.getVariable is the global repository, 
exchange.getVariable the route one; getRoute(id) returns null when unknown; 
getEndpoint creates the endpoint, hasEndpoint checks; the templates are created 
once and reused.

*Script variables*: there is no single helper, each language binds its own set, 
with different names, so this is a per-language card kept as hand-written text 
(the sets are Set.of / put literals outside camel-api, not annotatable) with a 
drift test in camel-jbang-core against the real constants:
* groovy: GroovyExpression.ExchangeBinding.EXCHANGE_VARIABLES = 
ExchangeHelper.populateVariableMap plus attachments and log: body, header(s), 
variable(s), exception, in, request, exchange, 
exchangeProperty/exchangeProperties, out, response, camelContext, attachments, 
log. No {{message}} variable.
* templates (velocity, freemarker, mvel, mustache, chunk, stringtemplate, 
thymeleaf, jslt): ExchangeHelper.populateVariableMap; exchange, camelContext, 
request only with allowContextMapAll.
* javascript, python: exchange, context, exchangeId, message, headers, 
properties, body (context and properties, not camelContext/exchangeProperties).
* python3: exchangeId, headers, properties, body; exchange, message, context 
only with host access.
* quickjs: body, headers, properties, exchangeId, variables, exception (JSON 
values, no host objects).
* java (joor): method parameters context, exchange, message, body, 
optionalBody; #bean: references become fields.

*Versioning*: none, the API is stable. One static set of cards; with 
camelVersion on an older catalog that has no api/ directory the tool answers 
from the CLI's own catalog.

Follow-up once the tool exists: the CAMEL-24698 hints in JavaChecks 
(exchange.setHeader), camel-groovy (bean name as variable) and the POJO 
aggregation strategy message point to {{camel_catalog_doc kind=api}} instead of 
restating the API.


> camel-catalog - a compact API reference of the core classes (Exchange, 
> Message, CamelContext, Registry, AggregationStrategy...) for AI assistants, 
> exposed as a catalog tool
> ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24708
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24708
>             Project: Camel
>          Issue Type: Improvement
>          Components: camel-catalog, camel-jbang
>            Reporter: Claus Ibsen
>            Priority: Major
>
> Add a compact API reference for the core Camel classes a route author's Java 
> or Groovy code touches, shipped in camel-catalog and exposed through the 
> camel-jbang-mcp tools (camel_catalog_doc with kind=api, or a 
> camel_catalog_api tool), so that an AI assistant, in particular a small local 
> model, can look the API up before writing code instead of guessing.
> Evidence (benchmark of AI-assisted route authoring against camel-jbang-mcp, 
> 2026-09-13, 18 runs with a local 35B model): 7 of the 109 defects found were 
> the model not knowing the Camel API rather than the DSL: oldExchange is null 
> on the first aggregation call, ${body.type} on a Map body, a bean with 
> several methods and no method name, a bean name used as a Groovy variable, a 
> two-parameter bean method called with only the body, exchange.setHeader(...) 
> called on the Exchange, the Groovy script variables. Each cost one to three 
> correction rounds; the answer was put into an error message every time, a 
> tool would give it up front.
> What it should return: not the javadoc, a card per class with one line per 
> method and the one-line usage a route author needs, about 60 lines in total 
> (2-3k tokens):
> - Exchange: getMessage() (getIn() is its alias), getProperty/setProperty, 
> getVariable, getContext, getException, isFailed; "the body and headers are on 
> the message"
> - Message: getBody(Class), setBody, getHeader(name, Class), setHeader, 
> getHeaders, removeHeader
> - CamelContext: getRegistry, createProducerTemplate, resolveLanguage; 
> Registry: lookupByName, lookupByNameAndType, bind
> - Processor, AggregationStrategy (with the first-call rule: oldExchange == 
> null, return newExchange), Predicate, Expression
> - the Groovy script variables (exchange, message, body, headers, variables, 
> exchangeProperties, camelContext, request, log) and how to reach a registry 
> bean from a script
> - a short "Camel 4 changes" block for models trained on older Camel (no 
> getOut(), header constants, getMessage())
> Source: a curated list of about ten classes in camel-catalog, generated at 
> build from the javadoc of the real methods so it cannot drift, plus a 
> hand-written "common mistakes" block per class. Stored next to the bean 
> metadata (org/apache/camel/catalog/api/*.json), so any tool and IDE can use 
> it.
> Frontier models mostly know this API and will rarely call the tool, which 
> costs nothing; they do get Camel-version details wrong, which the Camel 4 
> block addresses. For a local model it is the missing piece for anything with 
> a Java or Groovy bean. The validator messages of CAMEL-24698/CAMEL-24703 can 
> then point to the tool instead of restating the API.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to