Skip to content

Commit 370f0a3

Browse files
committed
Bedrock,GoogleGenAi: support toolExecutionMaxIterations
Signed-off-by: lambochen <[email protected]>
2 parents 5dc08fa + 59f2b3b commit 370f0a3

File tree

226 files changed

+15302
-1069
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

226 files changed

+15302
-1069
lines changed

.github/workflows/new-maven-central-release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ jobs:
2727
2828
- name: Release to Sonatype OSSRH
2929
env:
30-
SONATYPE_USER: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }}
31-
SONATYPE_PASSWORD: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }}
30+
CENTRAL_TOKEN_USERNAME: ${{ secrets.CENTRAL_TOKEN_USERNAME }}
31+
CENTRAL_TOKEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN_PASSWORD }}
3232
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
3333
run: |
3434
./mvnw -B clean install -DskipTests

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ shell.log
4343
/spring-ai-spring-boot-autoconfigure/nbproject/
4444
/vector-stores/spring-ai-cassandra-store/nbproject/
4545

46+
CLAUDE.md
4647
**/.claude/settings.local.json
4748
.devcontainer
4849

CONTRIBUTING.adoc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ For additional details, please refer to the blog post https://spring.io/blog/202
3232

3333
1. Go to https://github.com/spring-projects/spring-ai[https://github.com/spring-projects/spring-ai]
3434
2. Hit the "fork" button and choose your own GitHub account as the target
35-
3. For more detail see https://help.github.com/fork-a-repo/[Fork A Repo].
35+
3. For more detail see https://help.github.com/articles/fork-a-repo/[Fork A Repo].
3636

3737
== Setup your Local Development Environment
3838

@@ -140,16 +140,17 @@ However, we encourage all PR contributors to run checkstyles by enabling them be
140140

141141
You can enable them by doing the following:
142142

143-
```shell
143+
[source,shell]
144+
----
144145
./mvnw clean package -DskipTests -Ddisable.checks=false
145-
```
146+
----
146147

147148
=== Source Code Style
148149

149150
Spring AI source code checkstyle tries to follow the checkstyle guidelines used by the core Spring Framework project with some exceptions.
150151
The wiki pages
151-
[Code Style](https://github.com/spring-projects/spring-framework/wiki/Code-Style) and
152-
[IntelliJ IDEA Editor Settings](https://github.com/spring-projects/spring-framework/wiki/IntelliJ-IDEA-Editor-Settings)
152+
https://github.com/spring-projects/spring-framework/wiki/Code-Style[Code Style] and
153+
https://github.com/spring-projects/spring-framework/wiki/IntelliJ-IDEA-Editor-Settings[IntelliJ IDEA Editor Settings]
153154
define the source file coding standards we use along with some IDEA editor settings we customize.
154155

155156
== Mind the whitespace

advisors/spring-ai-advisors-vector-store/src/test/java/org/springframework/ai/chat/client/advisor/vectorstore/VectorStoreChatMemoryAdvisorTests.java

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919
import org.junit.jupiter.api.Test;
2020
import org.mockito.Mockito;
2121

22+
import org.springframework.ai.chat.prompt.PromptTemplate;
2223
import org.springframework.ai.vectorstore.VectorStore;
24+
import reactor.core.scheduler.Scheduler;
2325

26+
import static org.assertj.core.api.Assertions.assertThat;
2427
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2528

2629
/**
@@ -91,4 +94,116 @@ void whenDefaultTopKIsNegativeThenThrow() {
9194
.hasMessageContaining("topK must be greater than 0");
9295
}
9396

97+
@Test
98+
void whenBuilderWithValidVectorStoreThenSuccess() {
99+
VectorStore vectorStore = Mockito.mock(VectorStore.class);
100+
101+
VectorStoreChatMemoryAdvisor advisor = VectorStoreChatMemoryAdvisor.builder(vectorStore).build();
102+
103+
assertThat(advisor).isNotNull();
104+
}
105+
106+
@Test
107+
void whenBuilderWithAllValidParametersThenSuccess() {
108+
VectorStore vectorStore = Mockito.mock(VectorStore.class);
109+
Scheduler scheduler = Mockito.mock(Scheduler.class);
110+
PromptTemplate systemPromptTemplate = Mockito.mock(PromptTemplate.class);
111+
112+
VectorStoreChatMemoryAdvisor advisor = VectorStoreChatMemoryAdvisor.builder(vectorStore)
113+
.conversationId("test-conversation")
114+
.scheduler(scheduler)
115+
.systemPromptTemplate(systemPromptTemplate)
116+
.defaultTopK(5)
117+
.build();
118+
119+
assertThat(advisor).isNotNull();
120+
}
121+
122+
@Test
123+
void whenDefaultConversationIdIsBlankThenThrow() {
124+
VectorStore vectorStore = Mockito.mock(VectorStore.class);
125+
126+
assertThatThrownBy(() -> VectorStoreChatMemoryAdvisor.builder(vectorStore).conversationId(" ").build())
127+
.isInstanceOf(IllegalArgumentException.class)
128+
.hasMessageContaining("defaultConversationId cannot be null or empty");
129+
}
130+
131+
@Test
132+
void whenBuilderWithValidConversationIdThenSuccess() {
133+
VectorStore vectorStore = Mockito.mock(VectorStore.class);
134+
135+
VectorStoreChatMemoryAdvisor advisor = VectorStoreChatMemoryAdvisor.builder(vectorStore)
136+
.conversationId("valid-id")
137+
.build();
138+
139+
assertThat(advisor).isNotNull();
140+
}
141+
142+
@Test
143+
void whenBuilderWithValidTopKThenSuccess() {
144+
VectorStore vectorStore = Mockito.mock(VectorStore.class);
145+
146+
VectorStoreChatMemoryAdvisor advisor = VectorStoreChatMemoryAdvisor.builder(vectorStore)
147+
.defaultTopK(10)
148+
.build();
149+
150+
assertThat(advisor).isNotNull();
151+
}
152+
153+
@Test
154+
void whenBuilderWithMinimumTopKThenSuccess() {
155+
VectorStore vectorStore = Mockito.mock(VectorStore.class);
156+
157+
VectorStoreChatMemoryAdvisor advisor = VectorStoreChatMemoryAdvisor.builder(vectorStore).defaultTopK(1).build();
158+
159+
assertThat(advisor).isNotNull();
160+
}
161+
162+
@Test
163+
void whenBuilderWithLargeTopKThenSuccess() {
164+
VectorStore vectorStore = Mockito.mock(VectorStore.class);
165+
166+
VectorStoreChatMemoryAdvisor advisor = VectorStoreChatMemoryAdvisor.builder(vectorStore)
167+
.defaultTopK(1000)
168+
.build();
169+
170+
assertThat(advisor).isNotNull();
171+
}
172+
173+
@Test
174+
void whenBuilderCalledMultipleTimesWithSameVectorStoreThenSuccess() {
175+
VectorStore vectorStore = Mockito.mock(VectorStore.class);
176+
177+
VectorStoreChatMemoryAdvisor advisor1 = VectorStoreChatMemoryAdvisor.builder(vectorStore).build();
178+
VectorStoreChatMemoryAdvisor advisor2 = VectorStoreChatMemoryAdvisor.builder(vectorStore).build();
179+
180+
assertThat(advisor1).isNotNull();
181+
assertThat(advisor2).isNotNull();
182+
assertThat(advisor1).isNotSameAs(advisor2);
183+
}
184+
185+
@Test
186+
void whenBuilderWithCustomSchedulerThenSuccess() {
187+
VectorStore vectorStore = Mockito.mock(VectorStore.class);
188+
Scheduler customScheduler = Mockito.mock(Scheduler.class);
189+
190+
VectorStoreChatMemoryAdvisor advisor = VectorStoreChatMemoryAdvisor.builder(vectorStore)
191+
.scheduler(customScheduler)
192+
.build();
193+
194+
assertThat(advisor).isNotNull();
195+
}
196+
197+
@Test
198+
void whenBuilderWithCustomSystemPromptTemplateThenSuccess() {
199+
VectorStore vectorStore = Mockito.mock(VectorStore.class);
200+
PromptTemplate customTemplate = Mockito.mock(PromptTemplate.class);
201+
202+
VectorStoreChatMemoryAdvisor advisor = VectorStoreChatMemoryAdvisor.builder(vectorStore)
203+
.systemPromptTemplate(customTemplate)
204+
.build();
205+
206+
assertThat(advisor).isNotNull();
207+
}
208+
94209
}

auto-configurations/mcp/spring-ai-autoconfigure-mcp-client/pom.xml renamed to auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-common/pom.xml

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
<version>1.1.0-SNAPSHOT</version>
1010
<relativePath>../../../pom.xml</relativePath>
1111
</parent>
12-
<artifactId>spring-ai-autoconfigure-mcp-client</artifactId>
12+
<artifactId>spring-ai-autoconfigure-mcp-client-common</artifactId>
1313
<packaging>jar</packaging>
14-
<name>Spring AI MCP Client Auto Configuration</name>
15-
<description>Spring AI MCP Client Auto Configuration</description>
14+
<name>Spring AI MCP Client Common Auto Configuration</name>
15+
<description>Spring AI MCP Client Common Auto Configuration</description>
1616
<url>https://github.com/spring-projects/spring-ai</url>
1717

1818
<scm>
@@ -35,11 +35,11 @@
3535
<optional>true</optional>
3636
</dependency>
3737

38-
<dependency>
38+
<!-- <dependency>
3939
<groupId>io.modelcontextprotocol.sdk</groupId>
4040
<artifactId>mcp-spring-webflux</artifactId>
4141
<optional>true</optional>
42-
</dependency>
42+
</dependency> -->
4343

4444
<dependency>
4545
<groupId>org.springframework.boot</groupId>
@@ -53,15 +53,6 @@
5353
<optional>true</optional>
5454
</dependency>
5555

56-
<!-- NOTE: Currently the webmvc doesn't implement client transport.
57-
We will add it in the future based on ResrtClient.
58-
-->
59-
<!-- <dependency>
60-
<groupId>io.modelcontextprotocol.sdk</groupId>
61-
<artifactId>mcp-spring-webmvc</artifactId>
62-
<optional>true</optional>
63-
</dependency> -->
64-
6556
<!-- Test dependencies -->
6657
<dependency>
6758
<groupId>org.springframework.ai</groupId>
Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.ai.mcp.client.autoconfigure;
17+
package org.springframework.ai.mcp.client.common.autoconfigure;
1818

1919
import java.util.ArrayList;
2020
import java.util.List;
@@ -24,9 +24,9 @@
2424
import io.modelcontextprotocol.client.McpSyncClient;
2525
import io.modelcontextprotocol.spec.McpSchema;
2626

27-
import org.springframework.ai.mcp.client.autoconfigure.configurer.McpAsyncClientConfigurer;
28-
import org.springframework.ai.mcp.client.autoconfigure.configurer.McpSyncClientConfigurer;
29-
import org.springframework.ai.mcp.client.autoconfigure.properties.McpClientCommonProperties;
27+
import org.springframework.ai.mcp.client.common.autoconfigure.configurer.McpAsyncClientConfigurer;
28+
import org.springframework.ai.mcp.client.common.autoconfigure.configurer.McpSyncClientConfigurer;
29+
import org.springframework.ai.mcp.client.common.autoconfigure.properties.McpClientCommonProperties;
3030
import org.springframework.ai.mcp.customizer.McpAsyncClientCustomizer;
3131
import org.springframework.ai.mcp.customizer.McpSyncClientCustomizer;
3232
import org.springframework.beans.factory.ObjectProvider;
@@ -98,8 +98,14 @@
9898
* @see SseHttpClientTransportAutoConfiguration
9999
* @see SseWebFluxTransportAutoConfiguration
100100
*/
101-
@AutoConfiguration(after = { StdioTransportAutoConfiguration.class, SseHttpClientTransportAutoConfiguration.class,
102-
SseWebFluxTransportAutoConfiguration.class })
101+
@AutoConfiguration(afterName = {
102+
"org.springframework.ai.mcp.client.common.autoconfigure.StdioTransportAutoConfiguration",
103+
"org.springframework.ai.mcp.client.httpclient.autoconfigure.SseHttpClientTransportAutoConfiguration",
104+
"org.springframework.ai.mcp.client.httpclient.autoconfigure.StreamableHttpHttpClientTransportAutoConfiguration",
105+
"org.springframework.ai.mcp.client.webflux.autoconfigure.SseWebFluxTransportAutoConfiguration",
106+
"org.springframework.ai.mcp.client.webflux.autoconfigure.StreamableHttpWebFluxTransportAutoConfiguration" })
107+
108+
// @AutoConfiguration
103109
@ConditionalOnClass({ McpSchema.class })
104110
@EnableConfigurationProperties(McpClientCommonProperties.class)
105111
@ConditionalOnProperty(prefix = McpClientCommonProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.ai.mcp.client.autoconfigure;
17+
package org.springframework.ai.mcp.client.common.autoconfigure;
1818

1919
import java.util.List;
2020

@@ -23,7 +23,7 @@
2323

2424
import org.springframework.ai.mcp.AsyncMcpToolCallbackProvider;
2525
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
26-
import org.springframework.ai.mcp.client.autoconfigure.properties.McpClientCommonProperties;
26+
import org.springframework.ai.mcp.client.common.autoconfigure.properties.McpClientCommonProperties;
2727
import org.springframework.beans.factory.ObjectProvider;
2828
import org.springframework.boot.autoconfigure.AutoConfiguration;
2929
import org.springframework.boot.autoconfigure.condition.AllNestedConditions;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.ai.mcp.client.autoconfigure;
17+
package org.springframework.ai.mcp.client.common.autoconfigure;
1818

1919
import io.modelcontextprotocol.spec.McpClientTransport;
2020

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.ai.mcp.client.autoconfigure;
17+
package org.springframework.ai.mcp.client.common.autoconfigure;
1818

1919
import java.util.ArrayList;
2020
import java.util.List;
@@ -24,8 +24,8 @@
2424
import io.modelcontextprotocol.client.transport.StdioClientTransport;
2525
import io.modelcontextprotocol.spec.McpSchema;
2626

27-
import org.springframework.ai.mcp.client.autoconfigure.properties.McpClientCommonProperties;
28-
import org.springframework.ai.mcp.client.autoconfigure.properties.McpStdioClientProperties;
27+
import org.springframework.ai.mcp.client.common.autoconfigure.properties.McpClientCommonProperties;
28+
import org.springframework.ai.mcp.client.common.autoconfigure.properties.McpStdioClientProperties;
2929
import org.springframework.boot.autoconfigure.AutoConfiguration;
3030
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
3131
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2025-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ai.mcp.client.common.autoconfigure.aot;
18+
19+
import org.springframework.aot.hint.MemberCategory;
20+
import org.springframework.aot.hint.RuntimeHints;
21+
import org.springframework.aot.hint.RuntimeHintsRegistrar;
22+
23+
import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClassesInPackage;
24+
25+
/**
26+
* @author Josh Long
27+
* @author Soby Chacko
28+
* @author Christian Tzolov
29+
*/
30+
public class McpClientAutoConfigurationRuntimeHints implements RuntimeHintsRegistrar {
31+
32+
@Override
33+
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
34+
hints.resources().registerPattern("**.json");
35+
36+
var mcs = MemberCategory.values();
37+
for (var tr : findJsonAnnotatedClassesInPackage("org.springframework.ai.mcp.client.common.autoconfigure")) {
38+
hints.reflection().registerType(tr, mcs);
39+
}
40+
}
41+
42+
}

0 commit comments

Comments
 (0)