## Issue
Closes#5531
## Change
`DefaultServerSentEventParser` applied `content.trim()` to each `data:`
field value, removing all leading and trailing whitespace. The WHATWG
HTML Living Standard (Server-sent events, "Interpreting an event
stream") requires removing only a single leading U+0020 SPACE when
present; further leading whitespace and all trailing whitespace must be
preserved. The old behavior corrupted values with multiple leading
spaces, trailing spaces, or indentation, which matters for LLM token
streaming, the module's primary use.
This PR replaces `trim()` with a single-leading-space strip on the
`data:` branch only; `event:` handling is left unchanged to keep the
change minimal.
Added unit tests for preserving additional leading whitespace,
preserving trailing whitespace, and leaving values with no leading space
unchanged. Existing parameterized and multi-line tests remain green
(each line still loses one leading space).
Could a maintainer confirm whether the original `trim()` was intentional
normalization rather than a bug?
## General checklist
- [x] There are no breaking changes (API, behaviour)
- [x] I have added unit and/or integration tests for my change
- [x] The tests cover both positive and negative cases
- [x] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [ ] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
<!-- Not applicable: no new maven module, no embedding store integration
changes. -->
## Issue
<!-- Update with the real issue number once the issue above is filed -->
Closes#5506
## Change
`CassandraEmbeddingStore` builds its backing `MetadataVectorTable` with
the configured `CassandraSimilarityMetric` (COSINE, DOT_PRODUCT, or
EUCLIDEAN), exposed via `Builder.metric(...)` and
`BuilderAstra.metric(...)`.
But both `findRelevant(...)` overloads (reached by `search(...)`)
hardcoded `.metric(CassandraSimilarityMetric.COSINE)` on the `AnnQuery`.
A store configured with EUCLIDEAN or DOT_PRODUCT was therefore queried
with the COSINE CQL similarity function, returning wrong top-K results
on a normal call path with valid input.
This PR replaces the hardcoded COSINE with
`.metric(embeddingTable.getSimilarityMetric())` in both overloads, so
search honors the configured metric. The COSINE default path is
unchanged (backward compatible).
Scope: this PR fixes only the metric passed to the query. The
EUCLIDEAN/DOT_PRODUCT relevance-score mapping
(`RelevanceScore.fromCosineSimilarity`) is a separate design question,
left to a follow-up.
Tests: added `CassandraEmbeddingStoreTest` (Mockito `ArgumentCaptor`, no
Docker/API key). It captures the `AnnQuery` passed to `similaritySearch`
and asserts the metric matches the configured one for both overloads,
plus a COSINE-default case. Verified fail-then-pass: the EUCLIDEAN
assertions fail against the pre-fix code and pass after the fix.
Note: `CassandraEmbeddingStore.java` predates the palantir-java-format
ratchet, so `spotless:apply` reformatted the whole touched file (import
ordering, line wrapping) as CI requires. Functional change is the two
`.metric(...)` lines.
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [ ] I have manually run all the unit and integration tests in the core
and main modules <!-- change is isolated to langchain4j-cassandra -->
- [ ] I have added/updated the documentation <!-- bug fix; docs added
after approval per guidelines -->
- [ ] I have added an example in the examples repo <!-- not a big
feature -->
- [ ] I have added/updated Spring Boot starter(s) <!-- not applicable
-->
<!-- Checklist for adding new maven module: not applicable -->
<!-- Checklist for adding/changing embedding store integration: no
schema/persistence change; behavior fix only -->
## Issue
`MistralAiChatModel.doChat()` accesses
`mistralAiResponse.getChoices().get(0)` without checking whether
`choices` is null or empty. When the Mistral AI API (or an
OpenAI-compatible server fronted by it, e.g. vLLM/llama.cpp/Ollama in
OpenAI mode) returns a response with no choices — content filtering,
quota or rate-limit errors, malformed responses — this throws a cryptic
`IndexOutOfBoundsException` (empty list) or `NullPointerException`
(null) instead of a clear failure.
This is the same class of issue reported for `OpenAiChatModel` in #4810,
and complements the `content: null` null-guard recently added to
`MistralAiMapper.aiMessageFrom` in #5123. That guard covers *non-empty*
choices whose `message.content` is null; this PR covers the orthogonal
case of *empty/null* choices themselves. No existing issue covers the
empty-choices case for the MistralAI integration.
## Change
`MistralAiChatModel.doChat()` now checks
`isNullOrEmpty(mistralAiResponse.getChoices())` before the choices are
consumed and throws a descriptive `IllegalArgumentException`, mirroring
the guard already applied in `OpenAiChatModel` (see #4810):
```java
if (isNullOrEmpty(mistralAiResponse.getChoices())) {
throw new IllegalArgumentException("Mistral AI response has no choices");
}
```
`isNullOrEmpty` is the same helper already imported across the codebase.
No public API or behaviour change for well-formed responses; only the
previously-crashing path now throws a clear exception instead.
## Tests
Added `MistralAiChatModelEmptyChoicesTest`, mirroring the existing
`MistralAiChatModelToolCallsTest` /
`MistralAiChatModelReturnThinkingTest` style (uses `MockHttpClient`, no
API key required). Covers:
1.
`should_throw_IllegalArgumentException_when_response_has_empty_choices`
— empty `choices: []` list → `IllegalArgumentException` (previously
`IndexOutOfBoundsException`).
2.
`should_throw_IllegalArgumentException_when_response_has_null_choices` —
`choices` absent (deserializes to `null`) → `IllegalArgumentException`
(previously `NullPointerException`).
3. `should_return_chat_response_when_response_has_choices` — regression
guard: a well-formed single-choice response is still parsed correctly.
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
`mvn -pl langchain4j-mistral-ai -am test
-Dtest=MistralAiChatModelEmptyChoicesTest
-Dsurefire.failIfNoSpecifiedTests=false` → `Tests run: 3, Failures: 0,
Errors: 0, Skipped: 0`, BUILD SUCCESS.
- [ ] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
## Issue
Closes #
<!-- human: no issue required (test-coverage + Javadoc); remove this
line or omit if submitting without an issue. -->
## Change
Fix a typo in the 3-arg constructor Javadoc of
`HtmlToTextDocumentTransformer`: `Mep.of(...)` named a nonexistent type,
corrected to `Map.of("title", "#title")`.
Add one `HtmlToTextDocumentTransformerTest` case for the
`metadataCssSelectors` parameter the Javadoc documents: a selector
matching nothing resolves to an empty metadata value (JUnit5 + AssertJ).
No behaviour change.
//
The file is pre-palantir; with `ratchetFrom=origin/main`, touching it
forces full-file formatting, so the diff includes formatting-only churn.
This is CI-required, not a manual reformat.
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [ ] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green <!-- core+main compiled green as -am
dependencies of the module build; not run standalone -->
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
<!-- N/A: no docs/ change -->
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features) <!-- N/A: not a big feature -->
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable) <!-- N/A -->
<!-- Omitted "new maven module" section: no new module. -->
<!-- Omitted "new/changed embedding store" sections: not an embedding
store. -->
---
## Issue
Closes#4814
## Change
Added a null/empty guard for `getChoices()` in
`AzureOpenAiChatModel.doChat()` before accessing `.get(0)`.
**Before:**
```java
ChatChoice chatChoice = chatCompletions.getChoices().get(0);
```
**After:**
```java
if (isNullOrEmpty(chatCompletions.getChoices())) {
throw new IllegalArgumentException("Chat completion failed: no choices returned");
}
ChatChoice chatChoice = chatCompletions.getChoices().get(0);
```
This is consistent with the streaming counterpart
`AzureOpenAiStreamingChatModel` which already has this guard (line
287-288).
**Note:** No unit tests are added because the `OpenAIClient` is an Azure
SDK class that requires a real or mock Azure endpoint. The existing
tests in this module are integration tests (IT). The fix is a simple
null/empty guard with clear correctness from code inspection.
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [ ] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [X] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-java](https://redirect.github.com/actions/setup-java)
([changelog](be666c2fcd..03ad4de099))
| action | digest | `be666c2` → `03ad4de` |
---
> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](../issues/2069) for more information.
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/langchain4j/langchain4j).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjMuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIl19-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
<!--
Thank you so much for your contribution!
Please fill in all the sections below.
Please open the PR as ready for review (not as a draft), with tests and
documentation already included.
Please note that PRs with breaking changes, or without tests and
documentation, will be rejected.
Please note that PRs will be reviewed based on the priority of the
issues they address.
We ask for your patience. We are doing our best to review your PR as
quickly as possible.
Please refrain from pinging and asking when it will be reviewed. Thank
you for understanding!
-->
## Issue
<!-- Please specify the ID of the issue this PR is addressing. For
example: "Closes #1234" or "Fixes #1234" -->
Closes #
## Change
Resolve the `ChatModel` through `chatModelProvider` when creating the
`Summarizer` in `AgentBuilder.build()`. When an agent declares both
`summarizedContext` and a `@ChatModelSupplier` that takes an
`AgenticScope` parameter, the model is stored as `chatModelProvider` (a
`Function<AgenticScope, ChatModel>`) rather than as the model field
directly. The `Summarizer` was only reading model, which is null in this
case, causing `IllegalConfigurationException: Please specify either
chatModel or streamingChatModel` at invocation time.
## General checklist
<!-- Please double-check the following points and mark them like this:
[X] -->
- [X] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [ ] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
## Checklist for adding new maven module
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have added my new module in the root `pom.xml` and
`langchain4j-bom/pom.xml`
## Checklist for adding new embedding store integration
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have added a `{NameOfIntegration}EmbeddingStoreIT` that extends
from either `EmbeddingStoreIT` or `EmbeddingStoreWithFilteringIT`
- [ ] I have added a `{NameOfIntegration}EmbeddingStoreRemovalIT` that
extends from `EmbeddingStoreWithRemovalIT`
## Checklist for changing existing embedding store integration
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have manually verified that the
`{NameOfIntegration}EmbeddingStore` works correctly with the data
persisted using the latest released version of LangChain4j
A shared metadata key is no longer reported as a conflict when the
document and the source hold equal values, since nothing observable is
discarded in that case. Conflicts are now collected and logged as a
single warning per document instead of one per key, which matters for
parsers that copy whole metadata dictionaries out of a file.
When two conflicting values render identically but differ in type, the
type is appended so the warning does not name two values that look the
same.
## Issue
Related to #5541. **This PR intentionally does not close #5541** — the
Kotlin `parseAsync` divergence stays open and is addressed in 2.0 (see
"Follow-up" below).
## Change
`DocumentLoader.load()` forwards the `DocumentSource` metadata onto the
parsed `Document` with `putAll()`. When the parser and the source define
the same key (e.g. a custom `DocumentParser` that sets
`file_name`, or `ApachePdfBoxDocumentParser` /
`ApacheTikaDocumentParser` with `includeMetadata = true`, which copy
keys straight out of the file), the document value is dropped and
nothing is reported.
This PR keeps the existing "source wins" resolution — no behaviour
change, no breaking change — but stops it being silent, and stops batch
loaders losing documents invisibly:
**`langchain4j-core`**
- `DocumentLoader.load()` logs a warning naming the conflicting key
**and both values**, and points at the workaround:
```
Metadata key "file_name" is set both by the document ("report.pdf") and
by the source ("2024-report.pdf").
Keeping the source value and discarding the document value. To control
this, remove the key in your
DocumentParser before returning the Document.
```
- Javadoc on `DocumentLoader.load()` now states the collision behaviour
explicitly instead of just "forwards the source Metadata".
- `Metadata.merge()` reports the conflicting **values**, not only the
key names:
`Metadata keys are not unique. Common keys and their values:
{key2=("value2", "value3")}`
**Batch loaders** (`FileSystemDocumentLoader`,
`ClassPathDocumentLoader`, `AmazonS3DocumentLoader`,
`AzureBlobStorageDocumentLoader`, `GoogleCloudStorageDocumentLoader`,
`TencentCosDocumentLoader`,
`GitHubDocumentLoader`)
All seven swallow per-document exceptions and continue, so a caller can
silently receive a shorter `List<Document>` than expected. Each now logs
a summary when anything was lost:
```
Loaded 9997 of 10000 documents from '/docs'. Skipped 3 that failed to
load and 0 that were blank.
```
`FileSystemDocumentLoader` and `ClassPathDocumentLoader` additionally
pass the throwable to the logger instead of only its message, so
failures get a stack trace like the cloud loaders already did.
## Why not throw on collisions
An earlier revision of this PR made both `DocumentLoader.load()` and the
Kotlin `parseAsync` throw on collisions via `Metadata.merge()`. That
turns out to be the wrong fix for 1.x: every batch loader treats an
exception as "this file is broken, skip it". A perfectly readable
document would then be dropped from the result list purely because of a
metadata key name — replacing a silently discarded *value* with a
silently discarded *document*. The trigger is user data (keys authored
by whoever produced the PDF), not user code, so it is not something the
caller can reliably avoid.
A workaround exists today and needs no new API — decorate the parser to
drop the key:
```java
DocumentParser stripped = inputStream -> {
Document document = myParser.parse(inputStream);
document.metadata().remove(Document.FILE_NAME);
return document;
};
```
## Follow-up (2.0)
Collisions should not be resolved silently, but the fix needs two pieces
that only fit in a major release, and they have to land together:
- **Collisions fail by default**, with an explicit resolution strategy
to opt out (`sourceWins()`, `documentWins()`, or a custom resolver), so
the library never guesses which value was meant.
- **Bulk loading gets a real failure policy**: fail-fast by default,
explicit opt-in to tolerance, and failures returned as **data** rather
than only logged — so "throw" can never mean "document silently
vanishes".
Until then, the Kotlin `parseAsync` extension keeps throwing where the
Java path warns. That divergence is deliberate, and is why #5541 stays
open — better one behaviour change in 2.0 than two in a row.
## Notes for reviewers
- No API changes and no new dependencies; `revapi` is unaffected.
- The only `langchain4j-kotlin` change is a test assertion updated for
the new `Metadata.merge()` message. The Kotlin `parseAsync` main source
is back to `main`.
- `Metadata.merge()`'s exception **message** changed. The exception type
and the conditions that trigger it are unchanged; only assertions on the
exact message text are affected.
- `GoogleCloudStorageDocumentLoader` shows a larger diff than its change
warrants: its imports were already unformatted on `main` and only hit
the spotless ratchet now that the file is touched.
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [X] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
<!-- N/A — behaviour is documented in the Javadoc of
DocumentLoader.load() -->
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features) <!-- N/A -->
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable) <!-- N/A -->
---------
Co-authored-by: Dmytro Liubarskyi <ljubarskij@gmail.com>
Mistral returns the failure detail of a batch result line either as a JSON
object or as a bare JSON string. The latter made Jackson fail with
MismatchedInputException while parsing the output/error file, so a single
failed item broke the whole retrieve() call. The error is now normalized
into a map on deserialization, keeping the field type unchanged.
Progresses #3916.
## Change
Adds `AnthropicBatchChatModel`, an implementation of the core
`BatchChatModel` interface
(`submit` / `retrieve` / `cancel` / `list`) for the [Anthropic Message
Batches
API](https://docs.anthropic.com/en/docs/build-with-claude/batch-processing),
which processes many chat requests asynchronously at 50% of the standard
per-token price.
Each request is built through the same `createAnthropicRequest` path as
`AnthropicChatModel`, so per-request
parameters (tools, thinking, caching, etc.) behave identically in a
batch and in a single call. Results come
back in arbitrary order and are re-sorted to submission order by
generated `custom_id`s. Anthropic reports
only `in_progress` / `canceling` / `ended` at the batch level, so
`ended` maps to `BatchState.SUCCEEDED` and
the per-request `succeeded` / `errored` / `canceled` / `expired`
outcomes are surfaced as `BatchItemResult`s.
The batch endpoints are added to the existing hand-rolled
`AnthropicClient` as default methods that throw
`UnsupportedFeatureException`, so existing `AnthropicClient`
implementations keep compiling. No new
dependency. Chat requests only.
Covered by unit tests against a mock HTTP server (custom-id ordering,
success/error/canceled mapping, the
in-progress case that fetches no results until the batch ends, and
pagination). The integration test
`AnthropicBatchChatModelIT` (key-gated on `ANTHROPIC_API_KEY`) was also
run against the live Batches API and
passes, exercising submit / retrieve / list / cancel.
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [X] I have manually run all the unit and integration tests in the core
and main modules, and they are all green
- [X] I have added/updated the documentation
- [ ] I have added an example in the examples repo (only for "big"
features)
- [ ] I have added/updated Spring Boot starter(s) (if applicable)
---------
Co-authored-by: Dmytro Liubarskyi <ljubarskij@gmail.com>
## Summary
- Introduce a fluent `Builder` for `DoclingDocumentParser` with an
optional `Function<InBodyConvertDocumentResponse, String>`
(`documentTextExtractor`) to customize how document text is extracted
from the Docling conversion response
- Default behavior (markdown extraction) is preserved — the extractor
defaults to `response.getDocument().getMarkdownContent()`
- Deprecate the existing public constructors in favor of the builder,
delegating internally to the builder-based constructor
- Bump `docling-serve-api`/`docling-serve-client` version from 0.5.2 to
0.6.0
- Update documentation at
`docs/docs/integrations/document-parsers/docling.md` with builder usage
and custom extraction examples
## Test plan
- [x] All 17 unit tests pass (7 existing + 10 new) covering builder
construction, custom extractors (HTML, text, doctags), null/blank
extractor results, full response metadata access, and builder with
options
- [x] Integration test with custom extractor against real Docling
container (`DoclingDocumentParserIT`)
- [x] Verify backward compatibility — existing constructor-based tests
pass without modification
---------
Signed-off-by: Eric Deandrea <eric.deandrea@ibm.com>
## Issue
Closes#4796
## Change
Current vLLM returns the reasoning text of its OpenAI-compatible chat
responses in a `reasoning` field rather than `reasoning_content`, and
it's not just vLLM. OpenAI's own guidance for serving gpt-oss recommends
`reasoning` on chat completions responses, which is what prompted the
vLLM rename (vllm-project/vllm#27755). OpenRouter and Groq already use
`reasoning`, and SGLang is planning the same migration
(sgl-project/sglang#18219). `reasoning_content` came from DeepSeek and
is still what their API, llama.cpp and others return, so clients
realistically need to read both names for the foreseeable future.
Right now the module only parses `reasoning_content`, so
`returnThinking(true)` quietly returns null thinking against any of the
`reasoning` backends. Setting `thinkingFieldName` doesn't help because
it only affects how thinking is serialized back into request messages,
not response parsing.
This adds `@JsonAlias("reasoning")` on the `reasoningContent` builder
setters of `AssistantMessage` and `Delta`, so both field names
deserialize into `reasoningContent`. Serialization is untouched,
requests on the wire don't change, and `reasoning_content` keeps working
as before. Same approach that was suggested in the review of #5018
before that PR was closed.
Besides the unit tests I verified both models manually against a live
vLLM v0.25.1 server running a Qwen3.5 reasoning model: before the change
`thinking()` is null for `OpenAiChatModel` and `onPartialThinking` never
fires for the streaming model, after the change both come through.
## General checklist
- [x] There are no breaking changes (API, behaviour)
- [x] I have added unit and/or integration tests for my change
- [x] The tests cover both positive and negative cases
- [x] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [x] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
---------
Co-authored-by: Andrea Moccia <brokenlander@users.noreply.github.com>
## Issue
Closes#5838
## Change
`GoogleGenAiToolMapper.convertToGoogleSchema` copied a
`JsonObjectSchema`'s properties into a `HashMap` and never set Gemini's
`propertyOrdering`. `JsonObjectSchema` keeps the declared order (backed
by a `LinkedHashMap`), but the copy lost it, so the generated schema's
field order was effectively arbitrary. Since Gemini uses
`propertyOrdering` to decide field emission order, structured-output
responses and function-call arguments could come back with fields in a
non-deterministic order.
Fix:
- copy properties into a `LinkedHashMap` to keep the declared order;
- set `propertyOrdering` to the property keys for objects with more than
one property.
This matches the official google-genai Python SDK (`_transformers.py`
sets `property_ordering = list(properties.keys())` for objects with >1
property) and the Vertex module in this repo (`SchemaHelper` already
uses a `LinkedHashMap`). The mapper is shared by function-call parameter
schemas and `responseSchema`, so both are fixed. The change is additive:
no public API change (revapi clean).
## Tests
Added
`should_preserve_declared_property_order_and_set_property_ordering` and
`should_set_property_ordering_on_nested_object` to
`GoogleGenAiToolMapperTest`. Both fail on `main` (the first because the
`HashMap` reorders the keys, the second because `propertyOrdering` is
absent) and pass with the fix.
```
mvn -pl langchain4j-google-genai verify -DskipITs # 133 unit tests, 0 failures; spotless + revapi green
mvn -pl langchain4j-core,langchain4j test # core 1270, 0 failures; main green
```
Both touched paths are also covered end-to-end by the module's live ITs
that run in CI: `GoogleGenAiAiServiceWithToolsIT` (function calling) and
`GoogleGenAiAiServiceWithJsonSchemaIT` (structured output).
## General checklist
- [x] There are no breaking changes (API, behaviour)
- [x] I have added unit and/or integration tests for my change
- [x] The tests cover both positive and negative cases
- [x] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [x] I have manually run all the unit and integration tests in the core
and main modules, and they are all green
- [ ] I have added/updated the documentation
- [ ] I have added an example in the examples repo (only for "big"
features)
- [ ] I have added/updated Spring Boot starter(s) (if applicable)
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://redirect.github.com/actions/checkout)
([changelog](9c091bb21b..3d3c42e5aa))
| action | digest | `9c091bb` → `3d3c42e` |
---
> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](../issues/2069) for more information.
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/langchain4j/langchain4j).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Bumps
[webpack-dev-server](https://github.com/webpack/webpack-dev-server) from
5.2.5 to 5.2.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/webpack/webpack-dev-server/releases">webpack-dev-server's
releases</a>.</em></p>
<blockquote>
<h2>v5.2.6</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p>fix: allow <code>undefined</code> as the <code>Server</code>
constructor <code>options</code> argument again (by <a
href="https://github.com/bjohansebas"><code>@bjohansebas</code></a> in
<a
href="https://redirect.github.com/webpack/webpack-dev-server/pull/5695">#5695</a>)</p>
<p>Restores accepting <code>undefined</code> (defaulting it to
<code>{}</code>) for the <code>options</code>
argument, so passing a webpack config's optional <code>devServer</code>
field type-checks and works as before.</p>
</li>
<li>
<p>Protect the built-in state-changing routes
(<code>/webpack-dev-server/invalidate</code> and
<code>/webpack-dev-server/open-editor</code>) against cross-site request
forgery. Requests are now checked with <code>Sec-Fetch-Site</code>
(falling back to an <code>Origin</code>/<code>Host</code> comparison
when it is absent), so a cross-site page can no longer trigger a rebuild
or open a file in the editor. Same-origin requests, user-initiated
navigations, and non-browser clients (e.g. curl) are unaffected. (by <a
href="https://github.com/bjohansebas"><code>@bjohansebas</code></a> in
<a
href="https://redirect.github.com/webpack/webpack-dev-server/pull/5698">#5698</a>)</p>
</li>
<li>
<p>Handle malformed <code>Host</code> and <code>Origin</code> header
values gracefully when validating requests. (by <a
href="https://github.com/bjohansebas"><code>@bjohansebas</code></a> in
<a
href="https://redirect.github.com/webpack/webpack-dev-server/pull/5699">#5699</a>)</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/webpack/webpack-dev-server/blob/v5.2.6/CHANGELOG.md">webpack-dev-server's
changelog</a>.</em></p>
<blockquote>
<h2>5.2.6</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p>fix: allow <code>undefined</code> as the <code>Server</code>
constructor <code>options</code> argument again (by <a
href="https://github.com/bjohansebas"><code>@bjohansebas</code></a> in
<a
href="https://redirect.github.com/webpack/webpack-dev-server/pull/5695">#5695</a>)</p>
<p>Restores accepting <code>undefined</code> (defaulting it to
<code>{}</code>) for the <code>options</code>
argument, so passing a webpack config's optional <code>devServer</code>
field type-checks and works as before.</p>
</li>
<li>
<p>Protect the built-in state-changing routes
(<code>/webpack-dev-server/invalidate</code> and
<code>/webpack-dev-server/open-editor</code>) against cross-site request
forgery. Requests are now checked with <code>Sec-Fetch-Site</code>
(falling back to an <code>Origin</code>/<code>Host</code> comparison
when it is absent), so a cross-site page can no longer trigger a rebuild
or open a file in the editor. Same-origin requests, user-initiated
navigations, and non-browser clients (e.g. curl) are unaffected. (by <a
href="https://github.com/bjohansebas"><code>@bjohansebas</code></a> in
<a
href="https://redirect.github.com/webpack/webpack-dev-server/pull/5698">#5698</a>)</p>
</li>
<li>
<p>Handle malformed <code>Host</code> and <code>Origin</code> header
values gracefully when validating requests. (by <a
href="https://github.com/bjohansebas"><code>@bjohansebas</code></a> in
<a
href="https://redirect.github.com/webpack/webpack-dev-server/pull/5699">#5699</a>)</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="8a37b0ed89"><code>8a37b0e</code></a>
chore(release): new release (<a
href="https://redirect.github.com/webpack/webpack-dev-server/issues/5697">#5697</a>)</li>
<li><a
href="f21ed0f44a"><code>f21ed0f</code></a>
fix: handle malformed Host and Origin headers (<a
href="https://redirect.github.com/webpack/webpack-dev-server/issues/5699">#5699</a>)</li>
<li><a
href="80cd9eea54"><code>80cd9ee</code></a>
fix: reject cross-site requests to open-editor and invalidate endpoints
(<a
href="https://redirect.github.com/webpack/webpack-dev-server/issues/5698">#5698</a>)</li>
<li><a
href="308e853808"><code>308e853</code></a>
fix: handle undefined options in Server constructor (<a
href="https://redirect.github.com/webpack/webpack-dev-server/issues/5695">#5695</a>)</li>
<li><a
href="8b2b9151f4"><code>8b2b915</code></a>
chore: update branch references from v4 to v5 in workflow
configuration</li>
<li><a
href="870ed2258d"><code>870ed22</code></a>
chore: add v5 branch to release workflow triggers</li>
<li>See full diff in <a
href="https://github.com/webpack/webpack-dev-server/compare/v5.2.5...v5.2.6">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain4j/langchain4j/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [shell-quote](https://github.com/ljharb/shell-quote) from 1.8.4 to
1.10.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ljharb/shell-quote/blob/main/CHANGELOG.md">shell-quote's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/ljharb/shell-quote/compare/v1.9.0...v1.10.0">v1.10.0</a>
- 2026-07-10</h2>
<h3>Merged</h3>
<ul>
<li>[New] <code>parse</code>: add opt-in <code>splitUnquoted</code>
option for shell field-splitting of unquoted expansions <a
href="https://redirect.github.com/ljharb/shell-quote/pull/1"><code>[#1](https://github.com/ljharb/shell-quote/issues/1)</code></a></li>
</ul>
<h3>Commits</h3>
<ul>
<li>[Fix] <code>parse</code>: match nested <code>${...}</code> braces so
nested parameter expansion is consumed as one substitution <a
href="c0842c8a7a"><code>c0842c8</code></a></li>
<li>[Tests] <code>parse</code>: pin single-quote literalness and
unmatched-quote handling <a
href="a0d03e35c8"><code>a0d03e3</code></a></li>
<li>[readme] remove the space in js code fences so evalmd evaluates them
<a
href="2116fa36ae"><code>2116fa3</code></a></li>
<li>[Tests] <code>quote</code>: pin conservative escaping of
<code>=</code>, <code>@</code>, <code>^</code>, <code>,</code>,
<code>:</code>, <code>!</code> (<a
href="https://redirect.github.com/ljharb/shell-quote/issues/11">#11</a>)
<a
href="1c36f3ff77"><code>1c36f3f</code></a></li>
<li>[readme] document that <code>quote</code> outputs POSIX quoting, not
<code>cmd.exe</code>/PowerShell <a
href="100e96e0ff"><code>100e96e</code></a></li>
<li>[readme] document <code>parse</code>'s supported parameter-expansion
subset <a
href="e1c75cd6e4"><code>e1c75cd</code></a></li>
<li>[Fix] <code>parse</code>: a backslash inside single quotes must not
escape the closing quote <a
href="5d460a332b"><code>5d460a3</code></a></li>
<li>[readme] fix stale example outputs <a
href="2de86f5d44"><code>2de86f5</code></a></li>
<li>[Tests] <code>quote</code>: pin that a backslash with whitespace is
not doubled in single quotes (<a
href="https://redirect.github.com/ljharb/shell-quote/issues/14">#14</a>)
<a
href="190e236bcf"><code>190e236</code></a></li>
<li>[readme] <code>quote</code>: use output verbatim; do not re-quote it
(<a
href="https://redirect.github.com/ljharb/shell-quote/issues/11">#11</a>)
<a
href="1b364683b1"><code>1b36468</code></a></li>
<li>[Refactor] <code>parse</code>: fix swapped
<code>SINGLE_QUOTE</code>/<code>DOUBLE_QUOTE</code> variable names <a
href="801af5c935"><code>801af5c</code></a></li>
<li>[types] fix an error TS v6 ignores but v7 fails on <a
href="59bbf8b81b"><code>59bbf8b</code></a></li>
<li>[Dev Deps] update <code>@arethetypeswrong/cli</code>,
<code>evalmd</code> <a
href="a04d47516e"><code>a04d475</code></a></li>
<li>[Dev Deps] update <code>@arethetypeswrong/ci</code>,
<code>eslint</code> <a
href="d390f9a92b"><code>d390f9a</code></a></li>
<li>[Tests] <code>quote</code>: the tilde test escapes every
<code>~</code>, not just a leading one (<a
href="https://redirect.github.com/ljharb/shell-quote/issues/9">#9</a>)
<a
href="617d119795"><code>617d119</code></a></li>
</ul>
<h2><a
href="https://github.com/ljharb/shell-quote/compare/v1.8.4...v1.9.0">v1.9.0</a>
- 2026-06-24</h2>
<h3>Commits</h3>
<ul>
<li>[New] add types <a
href="dca6e21a02"><code>dca6e21</code></a></li>
<li>[Dev Deps] update <code>eslint</code> <a
href="9aa9e8f609"><code>9aa9e8f</code></a></li>
<li>[Fix] <code>parse</code>: finalize tokens in linear time
(GHSA-395f-4hp3-45gv) <a
href="7ff5488599"><code>7ff5488</code></a></li>
<li>[actions] update workflows <a
href="75e849741f"><code>75e8497</code></a></li>
<li>[actions] Windows + node 4/6/7: pin eslint to 9 before install,
since npm 2/3 cannot stage eslint 10<code>@types/esrecurse</code> <a
href="3fb739de44"><code>3fb739d</code></a></li>
<li>[actions] retry <code>npm install</code> on Windows to survive npm
2/3 staging-rename flake <a
href="abe0163293"><code>abe0163</code></a></li>
<li>[actions] Windows + node 5/7: install deps with a modern node <a
href="b4bafa2e7e"><code>b4bafa2</code></a></li>
<li>[Fix] <code>quote</code>: escape leading <code>~</code> to prevent
shell tilde-expansion <a
href="7a76c1a12d"><code>7a76c1a</code></a></li>
<li>[Dev Deps] update <code>auto-changelog</code>, <code>tape</code> <a
href="7184b4458b"><code>7184b44</code></a></li>
<li>[Dev Deps] apparently <code>jackspeak</code> is no longer in the
graph <a
href="9ba368a405"><code>9ba368a</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="64988d9a0e"><code>64988d9</code></a>
v1.10.0</li>
<li><a
href="617d119795"><code>617d119</code></a>
[Tests] <code>quote</code>: the tilde test escapes every <code>~</code>,
not just a leading one (<a
href="https://redirect.github.com/ljharb/shell-quote/issues/9">#9</a>)</li>
<li><a
href="59bbf8b81b"><code>59bbf8b</code></a>
[types] fix an error TS v6 ignores but v7 fails on</li>
<li><a
href="190e236bcf"><code>190e236</code></a>
[Tests] <code>quote</code>: pin that a backslash with whitespace is not
doubled in singl...</li>
<li><a
href="a04d47516e"><code>a04d475</code></a>
[Dev Deps] update <code>@arethetypeswrong/cli</code>,
<code>evalmd</code></li>
<li><a
href="b9545b39f4"><code>b9545b3</code></a>
[New] <code>parse</code>: add opt-in <code>splitUnquoted</code> option
for shell field-splitting of...</li>
<li><a
href="1b364683b1"><code>1b36468</code></a>
[readme] <code>quote</code>: use output verbatim; do not re-quote it (<a
href="https://redirect.github.com/ljharb/shell-quote/issues/11">#11</a>)</li>
<li><a
href="1c36f3ff77"><code>1c36f3f</code></a>
[Tests] <code>quote</code>: pin conservative escaping of <code>=</code>,
<code>@</code>, <code>^</code>, <code>,</code>, <code>:</code>,
<code>!</code> (<a
href="https://redirect.github.com/ljharb/shell-quote/issues/11">#11</a>)</li>
<li><a
href="e1c75cd6e4"><code>e1c75cd</code></a>
[readme] document <code>parse</code>'s supported parameter-expansion
subset</li>
<li><a
href="c0842c8a7a"><code>c0842c8</code></a>
[Fix] <code>parse</code>: match nested <code>${...}</code> braces so
nested parameter expansion is ...</li>
<li>Additional commits viewable in <a
href="https://github.com/ljharb/shell-quote/compare/v1.8.4...v1.10.0">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain4j/langchain4j/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [postcss](https://github.com/postcss/postcss) from 8.5.8 to
8.5.23.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/releases">postcss's
releases</a>.</em></p>
<blockquote>
<h2>8.5.23</h2>
<ul>
<li>Do not load source map without <code>opts.from</code> for security
reasons.</li>
</ul>
<h2>8.5.22</h2>
<ul>
<li>Fixed custom property losing semicolon before a comment (by <a
href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li>
</ul>
<h2>8.5.21</h2>
<ul>
<li>Fixed childless at-rule losing semicolon before comment (by <a
href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li>
<li>Fixed docs (by <a
href="https://github.com/isker"><code>@isker</code></a>).</li>
</ul>
<h2>8.5.20</h2>
<ul>
<li>Fixed missing space if <code>AtRule#params</code> is set after (by
<a
href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li>
<li>Fixed mixing AST error on warnings (by <a
href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li>
</ul>
<h2>8.5.19</h2>
<ul>
<li>Fixed cleaning <code>before</code> for new nodes inserted to
<code>Root</code> (by <a
href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li>
</ul>
<h2>8.5.18</h2>
<ul>
<li>Restricted loading previous source maps file to the
<code>opts.from</code> folder for security reasons (use <code>unsafeMap:
true</code> to disable the check).</li>
</ul>
<h2>8.5.17</h2>
<ul>
<li>Fixed <code>Maximum call stack size exceeded</code> error.</li>
<li>Fixed Prototype hijacking for <code>postcss.fromJSON()</code>.</li>
<li>Fixed <code>Input#origin()</code> for unmapped end position (by <a
href="https://github.com/chatman-media"><code>@chatman-media</code></a>).</li>
</ul>
<h2>8.5.16</h2>
<ul>
<li>Fixed <code>Input#origin()</code> position (by <a
href="https://github.com/mizdra"><code>@mizdra</code></a>).</li>
<li>Fixed <code>raws</code> after rehydrating a JSON AST (by <a
href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li>
<li>Fixed putting parent-less node in <code>nodes</code> of new node (by
<a
href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li>
<li>Fixed computing <code>offset</code> in <code>positionBy()</code> (by
<a
href="https://github.com/greymoth-jp"><code>@greymoth-jp</code></a>).</li>
<li>Fixed <code>rangeBy()</code> on <code>index: 0</code> (by <a
href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li>
</ul>
<h2>8.5.15</h2>
<ul>
<li>Fixed declaration parsing performance (by <a
href="https://github.com/homanp"><code>@homanp</code></a>).</li>
</ul>
<h2>8.5.14</h2>
<ul>
<li>Fixed custom syntax regression (by <a
href="https://github.com/43081j"><code>@43081j</code></a>).</li>
</ul>
<h2>8.5.13</h2>
<ul>
<li>Fixed <code>postcss-scss</code> commend regression.</li>
</ul>
<h2>8.5.12</h2>
<ul>
<li>Fixed reading any file via user-generated CSS.</li>
<li>Added <code>opts.unsafeMap</code> to disable checks.</li>
</ul>
<h2>8.5.11</h2>
<ul>
<li>Fixed nested brackets parsing performance (by <a
href="https://github.com/offset"><code>@offset</code></a>).</li>
</ul>
<h2>8.5.10</h2>
<ul>
<li>Fixed XSS via unescaped <code></style></code> in non-bundler
cases (by <a
href="https://github.com/TharVid"><code>@TharVid</code></a>).</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/blob/main/CHANGELOG.md">postcss's
changelog</a>.</em></p>
<blockquote>
<h2>8.5.23</h2>
<ul>
<li>Do not load source map without <code>opts.from</code> for security
reasons.</li>
</ul>
<h2>8.5.22</h2>
<ul>
<li>Fixed custom property losing semicolon before a comment (by <a
href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li>
</ul>
<h2>8.5.21</h2>
<ul>
<li>Fixed childless at-rule losing semicolon before comment (by <a
href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li>
<li>Fixed docs (by <a
href="https://github.com/isker"><code>@isker</code></a>).</li>
</ul>
<h2>8.5.20</h2>
<ul>
<li>Fixed missing space if <code>AtRule#params</code> is set after (by
<a
href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li>
<li>Fixed mixing AST error on warnings (by <a
href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li>
</ul>
<h2>8.5.19</h2>
<ul>
<li>Fixed cleaning <code>before</code> for new nodes inserted to
<code>Root</code> (by <a
href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li>
</ul>
<h2>8.5.18</h2>
<ul>
<li>Restricted loading previous source maps file to the
<code>opts.from</code> folder for security reasons (use <code>unsafeMap:
true</code> to disable the check).</li>
</ul>
<h2>8.5.17</h2>
<ul>
<li>Fixed <code>Maximum call stack size exceeded</code> error.</li>
<li>Fixed Prototype hijacking for <code>postcss.fromJSON()</code>.</li>
<li>Fixed <code>Input#origin()</code> for unmapped end position (by <a
href="https://github.com/chatman-media"><code>@chatman-media</code></a>).</li>
</ul>
<h2>8.5.16</h2>
<ul>
<li>Fixed <code>Input#origin()</code> position (by <a
href="https://github.com/mizdra"><code>@mizdra</code></a>).</li>
<li>Fixed <code>raws</code> after rehydrating a JSON AST (by <a
href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li>
<li>Fixed putting parent-less node in <code>nodes</code> of new node (by
<a
href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li>
<li>Fixed computing <code>offset</code> in <code>positionBy()</code> (by
<a
href="https://github.com/greymoth-jp"><code>@greymoth-jp</code></a>).</li>
<li>Fixed <code>rangeBy()</code> on <code>index: 0</code> (by <a
href="https://github.com/sarathfrancis90"><code>@sarathfrancis90</code></a>).</li>
</ul>
<h2>8.5.15</h2>
<ul>
<li>Fixed declaration parsing performance (by <a
href="https://github.com/homanp"><code>@homanp</code></a>).</li>
</ul>
<h2>8.5.14</h2>
<ul>
<li>Fixed custom syntax regression (by <a
href="https://github.com/43081j"><code>@43081j</code></a>).</li>
</ul>
<h2>8.5.13</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="eb9e1fe793"><code>eb9e1fe</code></a>
Release 8.5.23 version</li>
<li><a
href="9d19c78ac9"><code>9d19c78</code></a>
Update dependencies</li>
<li><a
href="7beca139e7"><code>7beca13</code></a>
Does no load source map file without opts.from</li>
<li><a
href="decea51421"><code>decea51</code></a>
Typo</li>
<li><a
href="c18e30d126"><code>c18e30d</code></a>
Update EM banner</li>
<li><a
href="98a39ad73d"><code>98a39ad</code></a>
Update EM banner</li>
<li><a
href="a3e48c492d"><code>a3e48c4</code></a>
Release 8.5.22 version</li>
<li><a
href="f49d691179"><code>f49d691</code></a>
Fix custom property losing its semicolon before a comment (<a
href="https://redirect.github.com/postcss/postcss/issues/2117">#2117</a>)</li>
<li><a
href="28e0daf8f2"><code>28e0daf</code></a>
Release 8.5.21 version</li>
<li><a
href="3d2b4e43e3"><code>3d2b4e4</code></a>
Update dependencies</li>
<li>Additional commits viewable in <a
href="https://github.com/postcss/postcss/compare/8.5.8...8.5.23">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new
releaser for postcss since your current version.</p>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain4j/langchain4j/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Vertex AI uses different hostnames for global, multi-region (us/eu), and
regional locations. Using the regional template for "global"/"us"/"eu"
previously produced a non-existent host that resolved via wildcard DNS
to an HTML 404 instead of a clear connection error.
Fixes#5865
<!--
Thank you so much for your contribution!
Please fill in all the sections below.
Please open the PR as ready for review (not as a draft), with tests and
documentation already included.
Please note that PRs with breaking changes, or without tests and
documentation, will be rejected.
Please note that PRs will be reviewed based on the priority of the
issues they address.
We ask for your patience. We are doing our best to review your PR as
quickly as possible.
Please refrain from pinging and asking when it will be reviewed. Thank
you for understanding!
-->
## Issue
<!-- Please specify the ID of the issue this PR is addressing. For
example: "Closes #1234" or "Fixes #1234" -->
Closes#5865
## Change
<!-- Please describe the changes you made. -->
## General checklist
<!-- Please double-check the following points and mark them like this:
[X] -->
- [x] There are no breaking changes (API, behaviour)
- [x] I have added unit and/or integration tests for my change
- [x] The tests cover both positive and negative cases
- [x] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [x] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [x] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
## Checklist for adding new maven module
<!-- Please double-check the following points and mark them like this:
[X] -->
- [x] I have added my new module in the root `pom.xml` and
`langchain4j-bom/pom.xml`
## Checklist for adding new embedding store integration
<!-- Please double-check the following points and mark them like this:
[X] -->
- [x] I have added a `{NameOfIntegration}EmbeddingStoreIT` that extends
from either `EmbeddingStoreIT` or `EmbeddingStoreWithFilteringIT`
- [x] I have added a `{NameOfIntegration}EmbeddingStoreRemovalIT` that
extends from `EmbeddingStoreWithRemovalIT`
## Checklist for changing existing embedding store integration
<!-- Please double-check the following points and mark them like this:
[X] -->
- [x] I have manually verified that the
`{NameOfIntegration}EmbeddingStore` works correctly with the data
persisted using the latest released version of LangChain4j
---------
Co-authored-by: Dmytro Liubarskyi <ljubarskij@gmail.com>
## Issue
Closes#5867
## Change
`AnthropicMapper` only applied `cache_control=ephemeral` to
`TextContent` when a
`UserMessage` was marked for caching, silently dropping it when the last
content
item was `ImageContent` or `PdfFileContent`. This contradicts the
surrounding
code comment ("apply the cache_control to the last content item") and
the
documented behavior in `anthropic.md`.
- Add `cacheControl`-accepting constructors and `from*` overloads to
`AnthropicImageContent` and `AnthropicPdfContent` (mirrors
`AnthropicTextContent`)
- In `AnthropicMapper`, pass `cacheControl` to Image/Pdf content when
`applyCache`
- Include `cacheControl` in `AnthropicPdfContent.toString()` (already
present on
`AnthropicImageContent` and `AnthropicTextContent`)
Only the user turn is affected, matching Anthropic's prompt caching
restriction.
Nested blocks inside `tool_result` are unchanged — sub-content blocks
cannot be
cached directly. Backward compatible: additive overloads; `cacheControl`
is null
when absent.
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [X] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
Co-authored-by: tianyu.zhao <mrzgetbetter820@users.noreply.github.com>
## Change
Add documentation page covering CDI framework features (AI service
injection, agentic topologies, MCP server, fault tolerance, telemetry,
guardrails) and supported runtimes (Quarkus, Helidon, WildFly, Payara,
GlassFish, Liberty).
## General checklist
<!-- Please double-check the following points and mark them like this:
[X] -->
- [X] There are no breaking changes (API, behaviour)
- [ ] I have added unit and/or integration tests for my change
- [ ] The tests cover both positive and negative cases
- [ ] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [ ] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [X] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
## Checklist for adding new maven module
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have added my new module in the root `pom.xml` and
`langchain4j-bom/pom.xml`
## Checklist for adding new embedding store integration
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have added a `{NameOfIntegration}EmbeddingStoreIT` that extends
from either `EmbeddingStoreIT` or `EmbeddingStoreWithFilteringIT`
- [ ] I have added a `{NameOfIntegration}EmbeddingStoreRemovalIT` that
extends from `EmbeddingStoreWithRemovalIT`
## Checklist for changing existing embedding store integration
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have manually verified that the
`{NameOfIntegration}EmbeddingStore` works correctly with the data
persisted using the latest released version of LangChain4j
Signed-off-by: Emmanuel Hugonnet <ehugonne@redhat.com>
<!--
Thank you so much for your contribution!
Please fill in all the sections below.
Please open the PR as ready for review (not as a draft), with tests and
documentation already included.
Please note that PRs with breaking changes, or without tests and
documentation, will be rejected.
Please note that PRs will be reviewed based on the priority of the
issues they address.
We ask for your patience. We are doing our best to review your PR as
quickly as possible.
Please refrain from pinging and asking when it will be reviewed. Thank
you for understanding!
-->
## Issue
<!-- Please specify the ID of the issue this PR is addressing. For
example: "Closes #1234" or "Fixes #1234" -->
Closes #
## Change
Introduce a configurable allowlist-based
`ConfigurablePolymorphicTypeValidator` that restricts which types can be
instantiated during `AgenticScope` JSON deserialization.
The list of allowed classes can be customized through the new
`allowDeserializationType` and `allowDeserializationPackagePrefix` of
the `AgenticScopeSerializer`.
When the deserialization meets an unknown class it throws a
`UnserializableAgenticScopeException` that names the rejected class and
suggests how to fix it.
## General checklist
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [ ] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
## Checklist for adding new maven module
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have added my new module in the root `pom.xml` and
`langchain4j-bom/pom.xml`
## Checklist for adding new embedding store integration
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have added a `{NameOfIntegration}EmbeddingStoreIT` that extends
from either `EmbeddingStoreIT` or `EmbeddingStoreWithFilteringIT`
- [ ] I have added a `{NameOfIntegration}EmbeddingStoreRemovalIT` that
extends from `EmbeddingStoreWithRemovalIT`
## Checklist for changing existing embedding store integration
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have manually verified that the
`{NameOfIntegration}EmbeddingStore` works correctly with the data
persisted using the latest released version of LangChain4j
## Issue
Closes#5863
## Change
`DefaultAgenticScope.rootCallEnded` resolved all pending async responses
with
`state.replaceAll(this::readStateBlocking)`, which throws
`NullPointerException` when a
response resolves to `null` (`ConcurrentHashMap.replaceAll` rejects a
null result).
Resolve them over a snapshot and write each result back through
`writeState`, which
removes the entry when the value is `null` matching the synchronous
behaviour:
```java
Map.copyOf(state).forEach((key, value) -> {
if (value instanceof DelayedResponse<?> pending) {
writeState(key, pending.blockingGet());
}
});
```
The remaining changes in the file are Spotless formatting (`ratchetFrom
origin/main`).
Tests (offline, no model), both fail on the current code with the raw
NPE and pass with the change:
- `DefaultAgenticScopeRootCallEndedTest` -- resolves a mix of
async-null, async-value and
plain state; asserts no throw, the null entry removed, the others
preserved.
- `AsyncAgentNullReturnParityTest` -- a POJO agent returning `null`
(output not read
downstream); the async run completes like the sync run.
```
mvn -pl langchain4j-agentic test
Tests run: 108, Failures: 0, Errors: 0, Skipped: 0
```
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [X] I have manually run all the unit and integration tests in the core
and main modules, and they are all green
- [ ] I have added/updated the documentation
- [ ] I have added an example in the examples repo (only for "big"
features)
- [ ] I have added/updated Spring Boot starter(s) (if applicable)
## Issue
Closes#5860
## Change
`SimpleToolSearchStrategy` lowercases tool names, descriptions and LLM
search terms with `String#toLowerCase()` without a `Locale`, so matching
depends on the JVM default locale.
Under the Turkish locale (`tr-TR`), `"listInvoices".toLowerCase()`
yields `"listınvoices"` (dotless i), which no longer contains the term
`"invoices"`. The tool is dropped from the results and the LLM gets `"No
matching tools found"`, contradicting the class Javadoc's "simple
case-insensitive `contains` matching".
Both lowercasing sites now go through the existing `lower()` helper with
`Locale.ROOT`, matching `DefaultToolExecutor` (#5778) and
`EnumOutputParser`. ASCII input is unaffected in every locale.
```java
private static String lower(String value) {
return value == null ? null : value.toLowerCase(Locale.ROOT);
}
```
This file predates Spotless formatting, so the `ratchetFrom origin/main`
reformats the whole file once it is touched. That reformat is isolated
in the first commit (`chore: apply spotless formatting to
SimpleToolSearchStrategy`); the second commit contains only the fix and
the test.
Tests: new `SimpleToolSearchStrategyLocaleTest` sets and restores the
default locale, mirroring `DefaultToolExecutorLocaleTest` (`@Isolated` +
`@Execution(SAME_THREAD)`, needed because this module runs tests in
parallel). It fails on `main` (score 0 instead of 3) and passes with
this fix.
## General checklist
- [ ] There are no breaking changes (API, behaviour) <!-- No signature
change, but search results do change under tr/az/lt locales — that
change is the fix. -->
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green <!-- `./mvnw -pl
langchain4j-core,langchain4j clean test` → 1272 tests green. *IT not run
— requires API keys. -->
- [X] I have manually run all the unit and integration tests in the core
and main modules, and they are all green <!-- core 1198 (5 skipped) +
main 1272, BUILD SUCCESS (JDK 17). -->
- [ ] I have added/updated the documentation <!-- N/A — behaviour fix,
no doc change needed. -->
- [ ] I have added an example in the examples repo (only for "big"
features) <!-- N/A — one-line bug fix. -->
- [ ] I have added/updated Spring Boot starter(s) (if applicable) <!--
N/A — no starter impact. -->
---------
Co-authored-by: Dmytro Liubarskyi <ljubarskij@gmail.com>
## Issue
Closes#5851
## Change
Mistral's provider-specific options (`safePrompt`, `randomSeed`,
`sendThinking`, `returnThinking`) were settable only at build time and
could not be varied per request. This adds
`MistralAiChatRequestParameters extends DefaultChatRequestParameters` so
they can be overridden per `ChatRequest`, on both `MistralAiChatModel`
and `MistralAiStreamingChatModel`.
```java
model.chat(ChatRequest.builder()
.messages(UserMessage.from("What is the best French cheese?"))
.parameters(MistralAiChatRequestParameters.builder()
.safePrompt(true)
.randomSeed(42)
.build())
.build());
```
- Backward compatible: the model builder options keep working and now
populate the default parameters.
- `strictJsonSchema` remains a model-level setting.
- `defaultRequestParameters()` return type is narrowed to
`MistralAiChatRequestParameters` (source- and binary-compatible; two
`revapi.json` entries added).
Tests: `MistralAiChatRequestParametersTest` (build, `EMPTY`,
`overrideWith`/`defaultedBy`, `toBuilder`, `equals`/`hashCode` incl.
cross-type) and `MistralAiChatModelParametersTest` /
`MistralAiStreamingChatModelParametersTest` (per-request options reach
the request body and override the model defaults, for both models). Docs
updated in `docs/docs/integrations/language-models/mistral-ai.md`.
## General checklist
- [x] There are no breaking changes (API, behaviour)
- [x] I have added unit and/or integration tests for my change
- [x] The tests cover both positive and negative cases
- [x] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [x] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [x] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
<!--
Thank you so much for your contribution!
Please fill in all the sections below.
Please open the PR as ready for review (not as a draft), with tests and
documentation already included.
Please note that PRs with breaking changes, or without tests and
documentation, will be rejected.
Please note that PRs will be reviewed based on the priority of the
issues they address.
We ask for your patience. We are doing our best to review your PR as
quickly as possible.
Please refrain from pinging and asking when it will be reviewed. Thank
you for understanding!
-->
## Issue
<!-- Please specify the ID of the issue this PR is addressing. For
example: "Closes #1234" or "Fixes #1234" -->
Closes #
## Change
When `compensateOnError(true)` is set on an agentic system, all
previously successful tool invocations with `@CompensateFor` actions are
compensated in reverse order if any tool in any sub-agent fails or any
agent throws.
This work is built on top of what has been done here
https://github.com/langchain4j/langchain4j/pull/5171
## General checklist
<!-- Please double-check the following points and mark them like this:
[X] -->
- [X] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [ ] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
## Checklist for adding new maven module
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have added my new module in the root `pom.xml` and
`langchain4j-bom/pom.xml`
## Checklist for adding new embedding store integration
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have added a `{NameOfIntegration}EmbeddingStoreIT` that extends
from either `EmbeddingStoreIT` or `EmbeddingStoreWithFilteringIT`
- [ ] I have added a `{NameOfIntegration}EmbeddingStoreRemovalIT` that
extends from `EmbeddingStoreWithRemovalIT`
## Checklist for changing existing embedding store integration
<!-- Please double-check the following points and mark them like this:
[X] -->
- [ ] I have manually verified that the
`{NameOfIntegration}EmbeddingStore` works correctly with the data
persisted using the latest released version of LangChain4j
## Issue
Closes#5849
## Change
On the streaming path, the A2A SDK calls the `DefaultA2AClientBuilder`
error handler with `null` to report a normal end of the stream
(`SSEEventListener.onComplete()`: *"null error means successful
completion"*), but the handler dereferenced its argument
unconditionally. If the stream ended before any event completed the
response future, the resulting `NullPointerException` skipped
`completeExceptionally(error)`, and `messageResponse.get()`, which has
no timeout, blocked forever.
The lambda moved into a package-private static `handleStreamEnd(...)` —
the seam `completeFromTask` already uses — where a `null` error now
completes a still-pending future with a `RuntimeException`. Non-null
errors are handled as before, and the non-streaming path never invokes
this handler.
```java
static void handleStreamEnd(Throwable error, CompletableFuture<String> messageResponse) {
if (error == null) { // the SDK signals a normal end of the stream
LOG.debug("SSE stream closed normally");
if (!messageResponse.isDone()) {
messageResponse.completeExceptionally(
new RuntimeException("A2A stream closed before a result was received"));
}
return;
}
// unchanged: log, and complete exceptionally if still pending
}
```
Four tests cover the new method: a `null` and a non-null error against a
pending and a completed future.
Follow-up: interrupted task states (`input-required`, `auth-required`)
go in a separate PR that delays completion further, so this one should
land first.
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [X] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
Testing: `langchain4j-agentic-a2a` (12 tests), `langchain4j-core` (1198)
and `langchain4j` (1270) are green. Integration tests were not run —
`A2AAgentIT` needs a running A2A server.
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
<!-- N/A — bug fix with no user-facing API change; docs are added after
review if requested. -->
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
<!-- N/A — not a feature. -->
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
<!-- N/A — no Spring Boot starter covers this module. -->
<!-- The conditional "new maven module" and "embedding store
integration" sections are omitted — neither applies to this PR. -->
## Issue
Closes#5846
## Change
`ParallelMapperPlanner.firstAction()` returned a bare `done()` when the
input collection was empty, so the agent returned `null`. The normal
path, `nextAction()`, builds a list (or array), writes it to
`outputKey`, and returns `done(result)`.
The result assembly moved into a private helper shared by both exit
paths, so an empty input now yields an empty `List` or zero-length
array, written to `outputKey`.
```java
if (items.isEmpty()) {
return doneWithResults(planningContext, new ArrayList<>());
}
```
- The `collectionObj == null` branch is untouched: a missing state key
means "no input at all", a separate question from "empty input".
- Returning an empty collection instead of `null` is a behaviour change.
For a typed mapper without an `@Output` method,
`ParallelMapperServiceImpl.isArrayResult()` already rejects any return
type that is not a `Collection` or an array, so `null` was never a valid
result — this restores the contract.
## Build/test notes
`ParallelMapperEmptyInputTest` covers list and array return types (the
array path goes through `Arrays.copyOf`), empty and non-empty. The two
empty-input tests fail on `main` and pass here.
`./mvnw -pl langchain4j-agentic -am clean test`: 91 tests green. `*IT`
classes need API keys and were not run.
`ParallelMapperPlanner.java` predates the Palantir format, so
`spotless:apply` also moves its existing static import to the top.
Included because `spotless:check` fails without it.
## General checklist
- [ ] There are no breaking changes (API, behaviour) — no API change;
behaviour changes from `null` to an empty collection on empty input,
which is the fix itself (see above)
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [ ] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green — unit tests green
(91 tests in `langchain4j-agentic`); `*IT` not run locally, they need
API keys
- [X] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green — unit tests only, via `./mvnw -pl
langchain4j-agentic -am clean test`
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
---------
Co-authored-by: Mario Fusco <mario.fusco@gmail.com>
## Issue
Closes#5845
## Change
Agents returned by `AgenticServices` are JDK dynamic proxies. Both
invocation handlers dispatched `Object` methods on a switch covering
only `toString` and `hashCode`, so `equals` hit the `default` branch and
threw `UnsupportedOperationException`.
That violates the `Object.equals` contract: `agent.equals(agent)` threw
instead of returning `true`, and `contains`/`remove`/`indexOf` threw on
any collection holding an agent.
This adds identity-based `equals` to both handlers, matching
`DefaultAiServices`:
```java
case "equals" -> proxy == args[0];
```
`hashCode` and `toString` are unchanged and stay consistent: two proxies
that are equal are the same object, so they always produce the same
hash. The only behaviour change is that a call which previously threw
now returns a boolean.
Could you confirm identity semantics are what you want?
`withAgenticScope` creates a new proxy per scope, so one logical agent
in different scopes compares as not equal. Happy to switch to
`agentId`-based comparison if you prefer.
## Build/test notes
`AgentProxyEqualsTest` covers both proxy paths — `agentBuilder`
(`AgentInvocationHandler`) and `sequenceBuilder`
(`PlannerBasedInvocationHandler`) — with a stub `ChatModel`, so no API
key is involved. All six tests fail on `main`.
`./mvnw -pl langchain4j-agentic -am clean test`: 93 tests green. `*IT`
classes need API keys, not run.
Both handlers predate the Palantir format, so `spotless:apply` reformats
them beyond the changed lines (import order, line wrapping). Included
because `spotless:check` fails without them.
## General checklist
- [X] There are no breaking changes (API, behaviour) — the only
behaviour change is that a call which previously threw now returns a
boolean
- [X] I have added unit and/or integration tests for my change
- [X] The tests cover both positive and negative cases
- [ ] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green — unit tests green
(93 tests in `langchain4j-agentic`); `*IT` not run locally, they need
API keys
- [X] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green — unit tests only, via `./mvnw -pl
langchain4j-agentic -am clean test`
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
## Issue
Fixes#5840
## Change
The "Asynchronous agents" tutorial example used
`AgenticServices.sequenceBuilder(...).executor(...)`, but
`SequentialAgentService` does not expose `executor()` (unlike
`ParallelAgentService` used with `parallelBuilder()`).
- Removed the invalid `.executor(Executors.newFixedThreadPool(2))` line
from the `sequenceBuilder` example in `docs/docs/tutorials/agents.md`.
- Clarified in the surrounding prose that async behavior is configured
with `.async(true)` on sub-agents, and that `executor()` applies to
parallel workflows only.
Parallel workflow examples that legitimately use `.executor(...)` on
`parallelBuilder()` / `parallelMapperBuilder()` are unchanged.
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [ ] I have added unit and/or integration tests for my change
(docs-only fix)
- [ ] The tests cover both positive and negative cases (N/A)
- [ ] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green (N/A — documentation
only)
- [ ] I have manually run all the unit and integration tests in the core
and main modules, and they are all green (N/A — documentation only)
- [X] I have added/updated the documentation
- [ ] I have added an example in the examples repo (N/A)
- [ ] I have added/updated Spring Boot starter(s) (N/A)
## Test plan
- [X] Reviewed the diff in `docs/docs/tutorials/agents.md`
- [X] Confirmed the async `sequenceBuilder` example no longer references
`executor()`
- [X] Confirmed parallel workflow examples still correctly document
`.executor(...)` on `parallelBuilder()`
Made with [Cursor](https://cursor.com)
Co-authored-by: arimu1 <19286898+arimu1@users.noreply.github.com>
Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from
42.7.11 to 42.7.12.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pgjdbc/pgjdbc/releases">org.postgresql:postgresql's
releases</a>.</em></p>
<blockquote>
<h2>v42.7.12: security</h2>
<h3>Silent channel-binding authentication downgrade
(CVE-2026-54291)</h3>
<p><code>channelBinding=require</code> connections can be silently
downgraded from SCRAM-SHA-256-PLUS (with channel binding) to plain
SCRAM-SHA-256 (without it), losing the man-in-the-middle protection the
setting is meant to guarantee. An attacker who can intercept the TLS
connection triggers the downgrade with a certificate whose signature
algorithm has no tls-server-end-point channel-binding hash. Examples are
Ed25519, Ed448, and post-quantum algorithms.</p>
<p>Two issues combine in releases 42.7.4 through 42.7.11:</p>
<p>The bundled <code>com.ongres.scram:scram-client</code> (3.1 or 3.2)
returns an empty byte array instead of failing when it cannot derive the
binding hash for such a certificate. This is the library issue tracked
as <a
href="https://github.com/ongres/scram/security/advisories/GHSA-p9jg-fcr6-3mhf">GHSA-p9jg-fcr6-3mhf</a>.</p>
<p>pgJDBC does not enforce channelBinding=require where it matters.
ScramAuthenticator checks only that the server advertised a -PLUS
mechanism; it neither rejects the empty binding nor checks that the
negotiated mechanism uses channel binding. The connection therefore
downgrades silently.</p>
<p>Only connections that set channelBinding=require are affected. Under
the default prefer policy, and under allow or disable, falling back to
plain SCRAM is the documented behaviour.</p>
<p>Releases before 42.7.4 are unaffected, because they do not support
channel binding.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md">org.postgresql:postgresql's
changelog</a>.</em></p>
<blockquote>
<h2>[42.7.12] (2026-06-29)</h2>
<h3>Security</h3>
<ul>
<li>fix: Enforce SCRAM channel-binding policy and prevent silent
downgrade.
Under <code>channelBinding=require</code>, the driver silently
downgraded from <code>SCRAM-SHA-256-PLUS</code> (with channel binding)
to plain <code>SCRAM-SHA-256</code> (without it) when the server
presented a certificate whose signature algorithm has no
<code>tls-server-end-point</code> channel-binding hash (e.g. Ed25519,
Ed448, or post-quantum algorithms). An attacker who can intercept the
TLS connection could exploit this to strip channel-binding protection.
The fix enforces channel binding in the driver's own code: it now fails
the connection when no binding data can be extracted, and verifies the
negotiated mechanism uses channel binding (<code>-PLUS</code>) when
<code>require</code> is set.
Only connections that set <code>channelBinding=require</code> are
affected. The default <code>prefer</code> policy and releases before
42.7.4 (which introduced channel-binding support) are unaffected.
See the <a
href="https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-j92g-9f8w-j867">Security
Advisory</a> for more detail.
The following <a
href="https://nvd.nist.gov/vuln/detail/CVE-2026-54291">CVE-2026-54291</a>
has been issued.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="77df98e4e6"><code>77df98e</code></a>
Merge commit from fork</li>
<li><a
href="68c53a4352"><code>68c53a4</code></a>
chore: bump version to 42.7.12</li>
<li>See full diff in <a
href="https://github.com/pgjdbc/pgjdbc/compare/REL42.7.11...REL42.7.12">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain4j/langchain4j/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Context
Fixes#3112
`OnnxScoringBertCrossEncoder.toScore()` casts the raw ONNX output to
`float[][]`. Some cross-encoder rerankers exported to ONNX (e.g.
`BAAI/bge-reranker-base` via Optimum) expose logits with shape `[batch,
1, 1]` (`float[][][]` / `[[[F`), so the cast throws:
```
java.lang.ClassCastException: class [[[F cannot be cast to class [[F
at OnnxScoringBertCrossEncoder.toScore(...)
```
## Change
Extract one logit per scored item in a shape-agnostic way via a new
package-private `extractLogits(Object value)` helper, handling both:
- **2D output** `[batch, k]` (`float[][]`) — historical behaviour, the
first logit of each item is used
- **3D output** `[batch, 1, 1]` (`float[][][]`) — as produced by
bge-reranker-base
Any other shape now raises a clear `IllegalStateException` instead of an
obscure `ClassCastException`.
## Verification
- Added `OnnxScoringBertCrossEncoderTest` (4 unit tests): 2D output, 3D
output (bge-reranker shape), multi-logit-per-item (historical behaviour
preserved), and unsupported shape.
- `./mvnw -pl langchain4j-onnx-scoring -am test
-Dtest=OnnxScoringBertCrossEncoderTest` → `Tests run: 4, Failures: 0,
Errors: 0, Skipped: 0`.
- `./mvnw spotless:apply` applied.
The change is backward compatible: 2D outputs produce identical scores,
it only additionally supports the 3D shape that previously crashed.
Co-authored-by: CountClaw <264466111+CountClaw@users.noreply.github.com>
## Issue
<!-- Comment-only correction (no runtime behaviour change) — no issue
required per typo-fix policy. -->
No issue — message-text correction only, no behaviour change.
## Change
`TablestoreEmbeddingStoreTest.testj_supported_value_types` is a guard
test: it fails when a new type is added to core
`Metadata#SUPPORTED_VALUE_TYPES`, and its failure message names the two
methods to update. The two method references were swapped:
- `rowToMetadata` was labelled "write logic", but `rowToMetadata(Row)`
reads a stored row into a `Metadata` (read).
- `innerAdd` was labelled "read logic", but `innerAdd(...)` writes
metadata into a `RowPutChange` and calls `putRow` (write).
A developer following the message would edit the wrong method. This
swaps the names to match the code (label order `1. write` / `2. read`
kept):
```java
.as("when Metadata#SUPPORTED_VALUE_TYPES add new types, we should modify:\n"
+ "1. write logic: innerAdd.\n"
+ "2. read logic: rowToMetadata")
```
The assertion (`isEqualTo(10)`) is unchanged.
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [ ] I have added unit and/or integration tests for my change <!-- N/A
— message-text fix, no behaviour to test; the existing assertion is
unchanged -->
- [ ] The tests cover both positive and negative cases <!-- N/A — see
above -->
- [X] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green <!--
TablestoreEmbeddingStoreTest: 13 passed (JDK 17). *IT gated by
TABLESTORE_* credentials, not run. -->
- [ ] I have manually run all the unit and integration tests in the core
and main modules, and they are all green <!-- N/A — change is confined
to one test-message string; no production/core code touched -->
- [ ] I have added/updated the documentation <!-- N/A -->
- [ ] I have added an example in the examples repo <!-- N/A -->
- [ ] I have added/updated Spring Boot starter(s) <!-- N/A -->
<!-- "new maven module" and "embedding store integration" checklists
omitted — not applicable (test-message fix in an existing module). -->
## Issue
No linked issue — test-coverage contribution (follow-up to #5492 in the
same module).
## Change
`GoogleAiGeminiChatRequestParameters` (google-ai-gemini module) carries
the Gemini-specific request parameters and the
`overrideWith`/`defaultedBy` merge logic, but had no dedicated unit
tests. This PR adds 8 tests covering:
- builder round-trip for all Gemini-specific parameters and null
defaults
- `imageAspectRatio` acting as an alias for `aspectRatio`
- `overrideWith(...)`: Gemini-specific values overridden by another
Gemini parameters instance, and preserved when overriding with common
`ChatRequestParameters`
- `defaultedBy(...)`: defaults applied from Gemini parameters, and
preserved when defaulted by common parameters
- `equals`/`hashCode` contract
Test-only change; no production code touched.
## General checklist
- [x] There are no breaking changes
- [x] I have added unit tests for my change (test-only PR, no
integration tests needed)
- [x] I have manually run all the unit tests in the
`langchain4j-google-ai-gemini` module and they are all green (354 tests,
0 failures; integration tests require a live API key and were not run)
- [x] Code is formatted with `spotless:apply`