## Issue
Closes#5751
## Change
Two complementary changes so the run_shell_command tool handles
timeout_seconds robustly — prevention at the schema level, containment
at the parse level.
1. Schema (prevention). ShellSkills registered timeout_seconds via
addStringProperty, even though the value is semantically an integer
(ShellCommandRunner.run(..., Integer timeoutSeconds, ...), described as
"The command timeout in seconds"). Advertising it as a string invites
the LLM to return non-integer text like "30 seconds", "1.5", or "". This
changes it to addIntegerProperty, so the schema communicates the
constraint to the model. RunShellCommandToolExecutor.resolveTimeout(...)
already had a first-class Integer branch, so no executor change is
needed for the happy path.
2. Parse guard (containment). JSON-schema adherence is not guaranteed
across providers — a model can still emit a string (or free text) for an
integer property. resolveTimeout(...) parsed the value with
Integer.valueOf(timeoutSeconds.toString()) and no guard, so a bad value
produced a raw NumberFormatException that propagated out of
executeWithContext, bypassing the tool's argument-error contract that
every
other argument error in this class honors. This wraps the parse and
routes NumberFormatException through the existing throwException(...)
path, mirroring parseArguments. A malformed timeout_seconds now yields
ToolExecutionException by default (message returned to the LLM), or
ToolArgumentsException when throwToolArgumentsExceptions(true).
The string-parse fallback in resolveTimeout is intentionally kept — it
remains the containment layer for providers that don't emit a strict
integer. The two layers together mean bad timeout values become rare
at the source and fail gracefully when they still occur.
Signature, public Java API, and the normal path (null, Integer, valid
numeric string) are unchanged. The schema type change affects only the
tool specification advertised to the LLM, in an experimental module.
Tests: two negative tests added — non-numeric timeout_seconds throws
ToolExecutionException under the default config and
ToolArgumentsException under throwToolArgumentsExceptions(true). The
existing positive
test_resolveTimeout still passes and covers both Integer (1) and String
("1") inputs, exercising the retained string fallback.
## 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 <!-- N/A — change is isolated to
experimental/langchain4j-experimental-skills-shell; core/main untouched
-->
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
<!-- N/A — bug fix, no doc change -->
- [ ] 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)
---------
Co-authored-by: Dmytro Liubarskyi <ljubarskij@gmail.com>
## Issue
Closes#5736
## Change
`SqlDatabaseContentRetriever.clean()` strips a markdown code fence from
the generated SQL before executing it. When the response has an opening
fence (```sql```/``````) but no closing fence, `substring(start,
lastIndexOf("```"))` gets `end < start` (`lastIndexOf` matches the
opening fence's own backticks) and throws
`StringIndexOutOfBoundsException`. `clean()` runs outside `retrieve()`'s
`try/catch`, so the exception escapes the retry / `emptyList()` fallback
the method is designed around.
This extracts the shared boundary logic into a `stripCodeFence` helper:
it slices to the closing fence only when one follows the opening tag,
otherwise returns the text after the opening tag. Behaviour for
correctly closed fences is unchanged.
Same underlying bug as #5731, fixed for `HibernateContentRetriever` in
#5732 (both classes independently implement the same fence-stripping
logic; `SqlDatabaseContentRetriever` was missed in that fix).
Added `SqlDatabaseContentRetrieverTest` (the module's first unit test —
`clean()` is `protected` and pure, so no live database is needed)
covering closed fences (regression), unclosed fences for both fence
types, and plain text.
## 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
---------
Co-authored-by: Benamira05 <145583236+Benamira05@users.noreply.github.com>
## Issue
Closes#5731
## Change
`HibernateContentRetriever.clean()` strips a markdown code fence from
the generated response before executing the HQL. When the response has
an opening fence (```` ```hql ````/```` ```sql ````/```` ``` ````) but
no closing fence, `substring(start, lastIndexOf("```"))` gets `end <
start` (`lastIndexOf` matches the opening fence's own backticks) and
throws `StringIndexOutOfBoundsException`. `clean()` runs outside
`retrieve()`'s `try/catch`, so the exception escapes the retry /
`emptyList()` fallback the method is designed around.
This extracts the shared boundary logic into a `stripCodeFence` helper:
it slices to the closing fence only when one follows the opening tag,
otherwise returns the text after the opening tag. Behaviour for
correctly closed fences is unchanged.
Added `HibernateContentRetrieverTest` (the module's first unit test —
`clean()` is `protected` and pure, so no live database is needed)
covering closed fences (regression), unclosed fences for all three fence
types, and plain text.
## 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 <!-- change confined to the
experimental-hibernate module; core/main not exercised -->
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
<!-- wait until reviewed/approved -->
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features) <!-- N/A — small bug fix -->
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable) <!-- N/A -->
<!-- "new maven module" and "embedding store integration" checklists
omitted — not applicable to this bug fix. -->
<!-- Testing done: JDK 17, `./mvnw -pl
experimental/langchain4j-experimental-hibernate test
-Dtest=HibernateContentRetrieverTest` → 7 tests green. Spotless verified
clean. IntegrationTests (HibernateContentRetrieverIT,
Testcontainers/Postgres) not run locally. -->
Co-authored-by: Dmytro Liubarskyi <ljubarskij@gmail.com>
## Issue
Closes#5455
## Change
`RunShellCommandToolExecutor.getRequiredArgument` guarded a missing
argument key, not a present-but-null value.
An LLM emitting `{"command": null}` produced `{command=null}`, so
`containsKey` passed the guard and `arguments.get(name).toString()`
threw a raw `NullPointerException`. That call runs before the `try` in
`executeWithContext`, so it escaped un-wrapped, bypassing the typed
`ToolExecutionException`/`ToolArgumentsException` selected by
`throwToolArgumentsExceptions`.
The fix resolves the value once and null-checks it, treating a null
value like a missing key with the same message. Backward compatible:
missing-key behavior and message unchanged; no signature change.
```java
private String getRequiredArgument(String argumentName, Map<String, Object> arguments) {
Object value = isNullOrEmpty(arguments) ? null : arguments.get(argumentName);
if (value == null) {
throwException("Missing required tool argument '%s'".formatted(argumentName));
}
return value.toString();
}
```
Added two negative-case unit tests to `RunShellCommandToolExecutorTest`:
`{"command": null}` yields `ToolExecutionException` (default) and
`ToolArgumentsException` (when `throwToolArgumentsExceptions(true)`).
## General checklist
- [X] There are no breaking changes (API, behaviour)
- [X] I have added unit and/or integration tests for my change
- [ ] The tests cover both positive and negative cases
<!-- Negative cases are the essential coverage for this fix (null value
-> typed exception). The pre-existing happy-path command execution is
already covered by existing tests; no new positive case was added. -->
- [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, and they are all green
<!-- N/A: this change is in
experimental/langchain4j-experimental-skills-shell, not core/main. -->
- [ ] 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)
<!-- Docs/examples to be added after review, per project policy. -->
<!-- N/A: no new maven module added. -->
<!-- N/A: no embedding store integration added or changed. -->
<!--
Thank you so much for your contribution!
Please fill in all the sections below.
Please open the PR as a draft initially. Once it is reviewed and
approved, we will ask you to add documentation and examples.
Please note that PRs with breaking changes or without tests 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
## Change
<!-- Please describe the changes you made. -->
Add new `HibernateContentRetriever`, similar to the existing SQL-based
one, but taking advantage of [Hibernate
ORM](https://github.com/hibernate/hibernate-orm/) and its new
`hibernate-assistant` module to provide:
- context initialization prompt based on the runtime metamodel (mapped
entity classes and corresponding db structures)
- constrained access only to the mapped tables and columns
- HQL (Hibernate Query Language) support, much closer to natural
language with advanced functionality
- `SELECT`-only queries, guaranteed by Hibernate's query parsing
- query results serialization, with handling of complex data types, lazy
properties and circular associations
## 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
<!-- Before adding documentation and example(s) (below), please wait
until the PR is reviewed and approved. -->
- [ ] 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`
## Issue
Closes https://github.com/langchain4j/langchain4j/issues/4396
## Change
Introduces support for [Agent Skills](https://agentskills.io/home)
# Skills
:::note
The Skills API is experimental. APIs and behavior may still change in
future releases.
:::
Skills is a mechanism for equipping an LLM with reusable, self-contained
behavioral instructions.
A skill bundles a name, a short description, and a body of instructions
(its _content_),
together with optional resources (e.g., references, assets, templates,
etc.).
The LLM loads a skill on demand, keeping the initial context small and
only pulling in
the detailed instructions when they are actually needed.
:::note
Skills are designed according to the [Agent Skills
specification](https://agentskills.io).
:::
## Creating Skills
### From the File System
Typically, each skill lives in its own directory containing a `SKILL.md`
file.
The file must start with a YAML front matter block that declares the
skill's `name` and `description`.
Everything below the front matter becomes the skill's content — the
instructions given to the LLM
when it activates the skill.
```
skills/
├── docx/
│ ├── SKILL.md
│ └── references/
│ └── tracked-changes.md ← loaded as a resource
└── data-analysis/
└── SKILL.md
```
Example `SKILL.md`:
```markdown
---
name: docx
description: Edit and review Word documents using tracked changes
---
When the user asks you to edit a Word document:
1. Always use tracked changes so edits can be reviewed.
...
```
Any file in the skill directory (other than `SKILL.md` itself and files
under a `scripts/`
subdirectory) is automatically loaded as a `SkillResource` that the LLM
can read on demand.
Use `FileSystemSkillLoader` from the `langchain4j-skills` module to load
skills from the file system:
```xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-skills</artifactId>
<version>1.12.0-beta20</version>
</dependency>
```
```java
// Load all skills found in immediate subdirectories:
List<FileSystemSkill> skills = FileSystemSkillLoader.loadSkills(Path.of("skills/"));
// Or load a single skill by its directory:
FileSystemSkill skill = FileSystemSkillLoader.loadSkill(Path.of("skills/docx"));
```
### Programmatically
Skills do not have to be file-system based.
You can create them from any source — a database, a remote API,
generated at runtime — using the builder API:
```java
Skill skill = Skill.builder()
.name("incident-response")
.description("Step-by-step runbook for diagnosing and resolving production incidents")
.content("""
When a production alert fires:
1. Call `fetchRecentLogs(serviceName)` to retrieve the last 5 minutes of logs.
2. Call `checkServiceHealth(serviceName)` to get current health metrics.
3. Based on the findings, call `createIncidentTicket(summary, severity)`.
4. If severity is CRITICAL, also call `pageOnCall(incidentId)`.
""")
.build();
```
You can also attach resources programmatically:
```java
SkillResource reference = SkillResource.builder()
.relativePath("references/tone-guide.md")
.content("Use warm, concise language. Avoid jargon.")
.build();
Skill skill = Skill.builder()
.name("customer-support")
.description("Handles customer support inquiries")
.content("Follow the tone guide in references/tone-guide.md ...")
.resources(List.of(reference))
.build();
```
## Modes
Skills can be integrated with an AI Service in two distinct modes,
depending on how much
control and trust you need.
### Tool Mode (Recommended)
**Class:** `Skills` (from the `langchain4j-skills` module)
This corresponds to the **Tool-based agents** integration approach
described in the
[Agent Skills specification](https://agentskills.io/integrate-skills).
In this mode, the LLM activates a skill to receive step-by-step
instructions, then carries
them out by calling the [tools](/tutorials/tools) you have explicitly
registered.
**The LLM has no access to the file system at inference time** — all
skill content and
resources are loaded into memory upfront (e.g. via
`FileSystemSkillLoader`), and the `activate_skill`
and `read_skill_resource` tools returns that preloaded content rather
than reading from disk.
Because only your pre-defined tools can be invoked, **there is no risk
of arbitrary code execution**.
#### Registered Tools
| Tool | When registered |
|-----------------------|-----------------------------------------------------------------------------------------------|
| `activate_skill` | Always. The LLM calls this to load a skill's full
instructions into the context. |
| `read_skill_resource` | When at least one skill has resources. The LLM
calls this to read individual reference files. |
#### How It Works
1. The system message lists the available skills (names and
descriptions) so the LLM can choose.
2. The user asks a question that requires a specific skill.
3. The LLM calls `activate_skill("my-skill")` to receive its
instructions.
4. The LLM follows those instructions to complete the task, optionally
reading resource files along the way.
#### Example Skill
Skills describe the _policy_ — the exact order of calls, required
arguments, error-handling steps,
and worked examples — while the actual execution stays in type-safe,
tested Java code:
```markdown
---
name: process-order
description: Processes a customer order end-to-end
---
To process an order:
1. Call `validateOrder(orderId)` to check the order is valid.
2. Call `reserveInventory(orderId)` to reserve the required stock.
3. Only if reservation succeeds, call `chargePayment(orderId)`.
4. Finally, call `sendConfirmationEmail(orderId)`.
If any step fails, call `rollbackOrder(orderId)` before reporting the error.
```
#### Wiring It Up
Pass the `ToolProvider` from `Skills` to your AI Service builder
alongside your regular tools.
Use `formatAvailableSkills()` to inject the skill catalogue into the
system message so
the LLM knows which skills it can activate:
```java
Skills skills = Skills.from(FileSystemSkillLoader.loadSkills(Path.of("skills/")));
MyAiService service = AiServices.builder(MyAiService.class)
.chatModel(chatModel)
.tools(new OrderTools()) // your tools
.toolProvider(skills.toolProvider()) // or .toolProviders(mcpToolProvider, skills.toolProvider())
.systemMessage("You have access to the following skills:\n" + skills.formatAvailableSkills()
+ "\nWhen the user's request relates to one of these skills, activate it first using the `activate_skill` tool before proceeding.")
.build();
```
`formatAvailableSkills()` returns an XML-formatted block listing each
skill's name and description:
```xml
<available_skills>
<skill>
<name>process-order</name>
<description>Processes a customer order end-to-end</description>
</skill>
<skill>
<name>data-analysis</name>
<description>Analyse tabular data and produce charts</description>
</skill>
</available_skills>
```
#### Customisation
The name, description, and parameter metadata of each tool can be
overridden through the
corresponding config class on the builder:
```java
Skills skills = Skills.builder()
.skills(mySkills)
.activateSkillToolConfig(ActivateSkillToolConfig.builder()
.name(...) // tool name (default: "activate_skill")
.description(...) // tool description
.parameterName(...) // parameter name (default: "skill_name")
.parameterDescription(...) // parameter description
.throwToolArgumentsExceptions(...) // throw ToolArgumentsException instead of ToolExecutionException (default: false)
.build())
.readResourceToolConfig(ReadResourceToolConfig.builder()
.name(...) // tool name (default: "read_skill_resource")
.description(...) // tool description
.skillNameParameterName(...) // skill_name parameter name (default: "skill_name")
.skillNameParameterDescription(...) // skill_name parameter description
.relativePathParameterName(...) // relative_path parameter name (default: "relative_path")
.relativePathParameterDescription(...) // static description (takes precedence over provider)
.relativePathParameterDescriptionProvider(...) // dynamic description based on available resources
.throwToolArgumentsExceptions(...) // throw ToolArgumentsException instead of ToolExecutionException (default: false)
.build())
.build();
```
### Shell Mode (Experimental)
**Class:** `ShellSkills` (from the
`langchain4j-experimental-skills-shell` module)
This corresponds to the **Filesystem-based agents** integration approach
described in the
[Agent Skills specification](https://agentskills.io/integrate-skills).
:::warning
**Shell execution is inherently unsafe.**
Commands run directly in the host process environment **without any
sandboxing, containerization,
or privilege restriction**. A misbehaving or prompt-injected LLM can
execute arbitrary commands
on the machine running your application.
Only use this in controlled environments where you fully trust the input
and accept
the associated risks.
:::
In this mode, the LLM is given a single `run_shell_command` tool and
reads skill instructions
directly from the file system using shell commands. There is no
`activate_skill` or
`read_skill_resource` tool — the LLM navigates skill files like a human
developer would.
#### Registered Tools
| Tool | When registered |
|---------------------|---------------------------------------------------------------------------------------------------|
| `run_shell_command` | Always. The LLM runs shell commands to read
`SKILL.md` files, resource files and execute scripts. |
#### How It Works
1. The system message lists available skills with their absolute
filesystem paths.
2. The user asks a question that requires a specific skill.
3. The LLM runs `cat /path/to/skills/docx/SKILL.md` to read the
instructions.
4. The LLM follows those instructions by running further shell commands.
#### Dependency
Shell execution lives in a separate experimental artifact — add it to
your build:
```xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-experimental-skills-shell</artifactId>
<version>1.12.0-beta20</version>
</dependency>
```
#### Wiring It Up
All skills must be filesystem-based (loaded via
`FileSystemSkillLoader`).
Use `ShellSkills` instead of `Skills`:
```java
ShellSkills skills = ShellSkills.from(FileSystemSkillLoader.loadSkills(Path.of("skills/")));
MyAiService service = AiServices.builder(MyAiService.class)
.chatModel(chatModel)
.toolProvider(skills.toolProvider()) // or .toolProviders(mcpToolProvider, skills.toolProvider())
.systemMessage("You have access to the following skills:\n" + skills.formatAvailableSkills()
+ "\nWhen the user's request relates to one of these skills, read its SKILL.md before proceeding.")
.build();
```
`formatAvailableSkills()` includes a `<location>` field so the LLM knows
exactly where to find each `SKILL.md`:
```xml
<available_skills>
<skill>
<name>docx</name>
<description>Edit and review Word documents using tracked changes</description>
<location>/path/to/skills/docx/SKILL.md</location>
</skill>
<skill>
<name>data-analysis</name>
<description>Analyse tabular data and produce charts</description>
<location>/path/to/skills/data-analysis/SKILL.md</location>
</skill>
</available_skills>
```
#### When to Use Shell Mode
This mode is best suited for **experimentation and prototyping**, or
when you want to use
third-party skills published by the community (e.g. from the
[agentskills.io](https://agentskills.io) ecosystem) without first
porting them to Java.
It lets you wire up a working workflow quickly, then migrate individual
actions
to tools as the solution matures.
#### Customisation
Use `RunShellCommandToolConfig` to tune the working directory, output
limits,
and parameter names:
```java
ShellSkills skills = ShellSkills.builder()
.skills(mySkills)
.runShellCommandToolConfig(RunShellCommandToolConfig.builder()
.name(...) // tool name (default: "run_shell_command")
.description(...) // tool description (default: includes OS name)
.commandParameterName(...) // command parameter name (default: "command")
.commandParameterDescription(...) // command parameter description
.timeoutSecondsParameterName(...) // timeout parameter name (default: "timeout_seconds")
.timeoutSecondsParameterDescription(...) // timeout parameter description
.workingDirectory(...) // working directory for commands (default: JVM's user.dir)
.maxStdOutChars(...) // max stdout chars in result (default: 10_000)
.maxStdErrChars(...) // max stderr chars in result (default: 10_000)
.executorService(...) // ExecutorService for reading stdout/stderr streams
.throwToolArgumentsExceptions(...) // throw ToolArgumentsException instead of ToolExecutionException (default: false)
.build())
.build();
```
## 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)
## Checklist for adding new maven module
- [X] I have added my new module in the root `pom.xml` and
`langchain4j-bom/pom.xml`
## Issue
Fixes https://github.com/langchain4j/langchain4j/issues/2918
## Change
- Changed `maxRetry` parameter semantics from "max attempts" to "max
retries".
- Changed default value of the `maxRetry` parameter from 3 to 2, but it
does not change the default behaviour. When `maxRetries` parameter is
not specified explicitly, it will attempt to execute up to 3 times (as
it was before).
## Breaking Change
If you do **_not_** specify `maxRetries` parameter explicitly, there is
no breaking change and you do not need to do any changes to your code.
If you specify `maxRetries` parameter explicitly, you will need to
reduce it by 1, example:
```java
// before
OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(GPT_4_O_MINI)
.maxRetries(1)
.build();
// after
OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(GPT_4_O_MINI)
.maxRetries(0)
.build();
```
## General checklist
- [ ] There are no breaking changes
- [ ] I have added unit and/or integration tests for my change
- [ ] 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)
## Change
Renamed `ChatLanguageModel` into `ChatModel` and
`StreamingChatLanguageModel` into `StreamingChatModel`.
All `chatLanguageModel(...)` methods were renamed into `chatModel(...)`,
all `streamingChatLanguageModel(...)` methods were renamed into
`streamingChatModel(...)`.
`DisabledChatLanguageModel` was renamed into `DisabledChatModel`,
`DisabledStreamingChatLanguageModel` into `DisabledStreamingChatModel`.
### OpenRewrite recipe:
```yml
---
type: specs.openrewrite.org/v1beta/recipe
name: dev.langchain4j.RenameChatModels
recipeList:
- org.openrewrite.java.ChangeType:
oldFullyQualifiedTypeName: dev.langchain4j.model.chat.ChatLanguageModel
newFullyQualifiedTypeName: dev.langchain4j.model.chat.ChatModel
- org.openrewrite.java.ChangeType:
oldFullyQualifiedTypeName: dev.langchain4j.model.chat.StreamingChatLanguageModel
newFullyQualifiedTypeName: dev.langchain4j.model.chat.StreamingChatModel
- org.openrewrite.java.ChangeType:
oldFullyQualifiedTypeName: dev.langchain4j.model.chat.DisabledChatLanguageModel
newFullyQualifiedTypeName: dev.langchain4j.model.chat.DisabledChatModel
- org.openrewrite.java.ChangeType:
oldFullyQualifiedTypeName: dev.langchain4j.model.chat.DisabledStreamingChatLanguageModel
newFullyQualifiedTypeName: dev.langchain4j.model.chat.DisabledStreamingChatModel
- org.openrewrite.java.ChangeMethodName:
methodPattern: dev.langchain4j..* chatLanguageModel(..)
newMethodName: chatModel
- org.openrewrite.java.ChangeMethodName:
methodPattern: dev.langchain4j..* streamingChatLanguageModel(..)
newMethodName: streamingChatModel
```
## General checklist
- [ ] There are no breaking changes
- [ ] I have added unit and/or integration tests for my change
- [ ] 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)
- [x] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)