Repository navigation
CAMEL-24961: camel-ai - the body types of openai, langchain4j-chat, a2a, docling, milvus, qdrant, ai-tool and ibm-watson-language - #28250
Conversation
…s, and the body it leaves after a step A @BodyTypes annotation on the endpoint, data format or language class says the body per side (consumerOut, consumerReply, producerIn, producerOut, marshal, unmarshal and expression in and out): its carriers (null, text, bytes, stream, file, value, map, list, pojo, unchanged, any, unknown), the Java type when it is always the same, the format, the options it depends on, the body for other option values, and a description. The package plugin writes it as a bodyTypes section of the catalog JSON and checks that each side fits the kind and that the options it names exist. A subclass declares its own. The first slice: file, direct, seda, timer, cron, kamelet, http, https, rest-openapi, xslt, sql and the json data format (jackson), read from the code that sets the body and checked against the body types the message history records when routes run. camel_catalog_doc returns them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
…tp, jms, kafka, aws2-sqs, the csv, jacksonXml and yaml data formats, and the languages The second slice of the catalog body types: - components: platform-http, rest (and the rest-openapi consumer), ftp, ftps, sftp, jms, activemq, activemq6, amqp, kafka, aws2-sqs, log, mock, scheduler, quartz; - data formats: csv, jacksonXml, snakeYaml; - languages: simple, constant, jsonpath, xpath, groovy, jq. Each value is read from the code that sets the body, and checked against the body types the message history recorded when the tests of the modules and reference routes ran (the ftp integration tests included). camel_catalog_doc gives the body types a line per side, and its answer is cut at 18000 characters instead of 16000, so the four sides of the jms components leave the options a limit asks for room. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
paho-mqtt5: the consumer gives the payload as a byte array, the producer sends what converts to one and leaves the body unchanged. mongodb: the consumer gives a Document (or null for a change without its full document with changeStreams); the producer takes a document or a query, and leaves a body by operation: a Document or null for a find of one, a List for findAll, findDistinct and aggregate, a Long for count, the result of the driver for the other writes. Read from the code that sets the body, and checked against a mosquitto and a mongodb container started with camel infra. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
…ts an option value without carriers
From the review of PR 28241:
- An iterator is read once and has no size and no index, so tooling that
reads list as a List accepts ${body.size()} or ${body[0]} on it, which fail
at runtime. The new iterator carrier names it: sql with outputType=StreamList
gives an iterator, not a list.
- A @BodyType.When with no carriers (carrier = {}) wrote "carriers": [] into
the catalog. The build now rejects it, as it does a side without carriers.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
…MEL-24961-catalog-body-types-2 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
… camel_catalog_doc says unknown for no carriers From the review of PR 28242: - The csv data format with lazyLoad=true gives an iterator, with the iterator carrier of PR 28241, not a list. - camel_catalog_doc says unknown for a body without carriers, instead of failing. The build rejects it now, but a catalog read from elsewhere may have one. - Sqs2Endpoint imports org.apache.camel.spi.* already: only the import of the nested BodyType.Carrier stays. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
…types of the catalog instead of their own tables The YAML validator's body walks read what a component or a data format does with the body from the catalog, instead of from tables in their source: - the consumer a route starts with (consumerOut): the file as read, text, bytes or data, instead of the file consumer only; - the body after a to: (producerOut): unchanged for log and mock and now for a file write, the response of the http producer as bytes or a stream; - the producers that need text (producerIn), instead of file, ftp, ftps and sftp only; - the body after an unmarshal (unmarshalOut), instead of the json, jacksonXml, yaml and csv table and the options that make something else; - the consumers that reply with text (consumerReply), instead of platform-http; - the consumers that give no body, instead of timer, quartz, scheduler and cron. A side holds for a step only when the step decides every option it depends on: an option the component can also be configured with (the valueDeserializer of kafka) counts only when the endpoint sets it, and a placeholder value is not known. The catalog of an older Camel version has no body types, so the validator's own catalog stands in for it. After a step that fails at runtime the walk stops, so a file write that keeps the body is reported once. The rules about HTTP methods, REST bindings and EIPs stay in the validator; the EIPs get body types with CAMEL-25928. The same reports as before on 1204 human-written route files (the Camel repository, the examples, kamelets, camel-k and camel-kit) and on 1209 model-written ones (the r17 benchmark series), and the doc examples of the validator tests still validate. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
…docling, milvus, qdrant, ai-tool and ibm-watson-language The AI components declare the body they need and the body they leave, per operation where the operation decides it. The answer of openai and langchain4j-chat is text, also when it is asked for JSON, so the YAML validator now reports a field read on it that has no unmarshal before. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
… endpoint count for its body types The operation of openai is in the path (openai:embeddings), so the validator reads the path options with the syntax of the component, as the catalog parses an endpoint. A path the catalog cannot read, such as a toD with an expression, says nothing about its options. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
…pe for a value its option cannot have A byOption value must be one of the enum of its option, or true or false for a boolean, ignoring case as tooling compares it with the endpoint: a misspelled operation such as embedding for embeddings would never hold. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
LGTM. No issues found.
Clean enhancement: @BodyTypes annotations on 8 AI component endpoints, readPath() correctly handles null URIs, dynamic URIs (falls through to configurable), and static path options. checkValue() NPE safety is guaranteed by checkOption() running first. The new test covers all three cases (static path → error, list indexing → ok, dynamic path → silent). Enum values in the annotations were verified against the component models.
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:
|
The attribute holds an array, and the catalog JSON and BodyTypeModel call the same field carriers. The Javadoc of BodyTypeModel.isUnknown() says that a side with no carriers is unknown too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
…MEL-24961-catalog-body-types-2
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
…AMEL-24961-catalog-body-types-3
…AMEL-24961-catalog-body-types-ai # Conflicts: # tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
…e data format and language schemas Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
gnodet-bot
left a comment
There was a problem hiding this comment.
Following up on my earlier review — previous findings are all addressed.
The new commit (1ef9d76) is a clean mechanical rename of the carrier field to carriers in every @BodyType.When annotation across A2AEndpoint, DoclingEndpoint, and LangChain4jChatEndpoint. The rename is applied consistently across all occurrences in all three files. No logic change, no runtime behavior change — this is a pure API alignment with the updated @BodyType.When annotation definition in the parent stack. LGTM.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
…-types' into feature/CAMEL-24961-catalog-body-types-2
…AMEL-24961-catalog-body-types-3
…AMEL-24961-catalog-body-types-ai
…n read as a list, as the carriers do Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
…AMEL-24961-catalog-body-types-3
…AMEL-24961-catalog-body-types-ai
…atalog-body-types-3 Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
…AMEL-24961-catalog-body-types-ai
…atalog-body-types-ai # Conflicts: # docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc # dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java # dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java
Stacked on #28246. This is the AI group of the catalog body types (CAMEL-24961). The group is openai, langchain4j-chat, a2a, docling, milvus, qdrant, ai-tool and ibm-watson-language: of the components the human-written routes use, these are the ones used most that had no body types yet.
What the catalog says now
any: the prompt, whichuserMessagecan replace. audio, image-edit, batch and decisions take their own bodytext. Withstreaming=true, aniterator. WithautoToolExecution=false, the tool calls. Per operation: embeddings gives alist, audio-speechbytes, batch-results aniterator, decisions a Decision, and batch and moderation keep the bodyany. CHAT_SINGLE_MESSAGE_WITH_PROMPT takes amap, CHAT_MULTIPLE_MESSAGES alisttexttext,bytes,stream,fileorpojo(a Message). The task and push config operations read headerstext. Per operation anddataFormat: aniteratorof events, alistof tasks, a configany, asCamelDoclingInputFilePathcan replace the body. The batch operations take alisttext. A DoclingDocument, a status, metadata, or the batch and chunk resultspojo: the request of the SDKpojo: the result of the SDKpojo,listornull, by the action headerlist,pojoorunchangedany, as a header can give the textpojo: AnalysisResultsThe consumers:
dataFormat=POJO) and replies with text or a Message;Checked at runtime against llama3.2 on a local Ollama, through its OpenAI API:
jsonSchema;streaming=true, an Iterator of ChatCompletionChunk;autoToolExecution=false, ajava.util.Optionalof the tool calls; when the tools run, a String;The local server was not started for embeddings, so I took that body from the SDK, where
Embedding.embedding()returns aList<Float>. The other components were read from their code.Two changes, for openai
openai:embeddings). A path the catalog cannot read, such as atoDwith an expression, says nothing about its options.byOptionvalue that its option cannot have: it must be a value of the enum, or true or false for a boolean, ignoring case. A misspelledembeddingwould otherwise never hold. The 166 values in the catalog pass.When a header can replace the body. Tooling cannot see headers. The prompt of openai, the text of Watson and the file of docling can each come from a header, and then the body is not used. So those inputs are
any, and the description says what the body must be without the header. This way the validator never reports a body that a header replaces.Measured. I ran the validator over the 1204 human-written and 1209 model-written route files: the reports are the same as with #28246. The human files use openai 7 times, a2a 5, langchain4j-chat 2, ibm-watson-language 2, and milvus, qdrant and ai-tool once each. None reads a field of the text answer without an unmarshal: the milvus example splits the text with
${body.trim().split(';')[0]}.Tests
TextBodyFlowTest.testTheOptionsInThePathOfTheEndpoint:llm:embeddingsgives a List;toDwith an expression in the path says nothing.EndpointSchemaGeneratorMojoTest: a value the option does not have.Docs: the validation page has the openai example, and the catalog page lists the new build check.
Claude Code on behalf of davsclaus
🤖 Generated with Claude Code