2.0.0#1697
Conversation
…son 3 Brings the agent platform stack onto the Spring Boot 4 line. Cascades through Spring Framework 7, Spring AI 2.0.0-M8, Jackson 3 (tools.jackson.*), Kotlin 2.2.21 (K2), and JUnit 6. Spring AI 2.0 API changes: - ChatClient.options() now takes ChatOptions.Builder<*>; bake chatOptions into the Prompt itself (preserves the ToolCallingChatOptions subtype through the advisor chain) and embed toolCallbacks via ToolCallingChatOptions.Builder so they survive the chatModel-defaults merge in addition to the spec-level .toolCallbacks() call. - Generation.getResult() / Message.getText() are now nullable; added the required !! / ?: dereferences at call sites. - Usage is non-null in 2.0; updated test mocks accordingly. - StructuredOutputConverter added getJsonSchema(); JacksonOutputConverter exposes it via a private val. - MCP customizer unified: McpSyncClientCustomizer + McpAsyncClientCustomizer → McpClientCustomizer. - MCP clientCapabilities is now non-null in test mocks. - ModelOptionsUtils.jsonToMap removed; replaced with objectMapper.readValue. Jackson 3 migration (tools.jackson.*): - POM groupIds: com.fasterxml.jackson.module/dataformat → tools.jackson.*; spring-boot pulls both jackson-bom (2.x) and tools.jackson:jackson-bom (3.x). - jackson-datatype-jsr310 removed — JavaTimeModule is built into Jackson 3. - ObjectMapper is now immutable; JsonMapper.builder() / rebuild() pattern for lenientMapper customization. - ValueDeserializer (was JsonDeserializer); ContextualDeserializer merged in. - propertyName / propertyNames (was fieldName / fieldNames). - WRITE_DATES_AS_TIMESTAMPS relocated to DateTimeFeature. - Custom MaybeReturnDeserializer rewritten against the Jackson 3 API. - Jackson 3 throws IllegalArgumentException/JacksonException (was IOException) for unserializable graphs; loosened test assertions accordingly. Spring Boot 4: - Jackson2ObjectMapperBuilder is no longer auto-configured; embabelJackson- ObjectMapper now builds via jacksonObjectMapper() directly and is autowire-eligible (dropped defaultCandidate=false) so generic ObjectMapper injections in integration tests resolve. - spring-retry was removed from the Boot 4 BOM but the API we use is unchanged; kept the library as a direct dep (spring-retry 2.0.12) rather than migrating to org.springframework.core.retry. - @AutoConfigureMockMvc moved to the new spring-boot-webmvc-test artifact under a different package; removed from CustomValidationAnnotationTest since it didn't actually use MockMvc. Spring Framework 7 / Kotlin 2.2.21 / JSpecify: - @NullMarked enforcement on Spring AI / Spring core / Jackson 3 supertypes cascades T : Any bounds into our overrides. Added -Xjspecify-annotations= ignore to embabel-build to suppress JSpecify-derived bound errors and reverted most <T : Any> bound additions, keeping them only at the unavoidable boundary (7 converter classes that directly extend Spring AI's StructuredOutputConverter / Spring's ObjectProvider). - Cast outputClass to Class<Any> at 4 converter-construction sites so unbounded <O> enclosing methods can still construct the bounded converters. - AutoRegistration ApplicationListener<ContextRefreshedEvent> bound dropped the redundant ? per Spring 7's stricter signatures. ArchUnit / victools / Jackson 3 schema generation: - victools 5.0.0 (Jackson 3 native) pulled transitively by Spring AI 2.0. - ObjectNode.deepCopy() returns ObjectNode directly (no type arg). - Schema "required" field may now nest arrays; flattened in two test sites. Tests: - FakeChatModel defaults switched from DefaultChatOptions to ToolCallingChatOptions so the prompt.options merge preserves the subtype. - 3 assertions on prompt.options.toolCallbacks count relaxed — Spring AI 2.0 routes spec toolCallbacks through ToolCallAdvisor internally rather than mirroring them onto the final prompt seen by ChatModel.call(). - assertThrows<X?> → assertThrows<X> (JUnit 6 @NullMarked). - Many test helpers bounded <T : Any> to match migrated main-source signatures. POM: - kotlin.version 2.1.10 → 2.2.21; kotlin.compiler.apiVersion 2.1 → 2.2. - spring-boot.version 4.0.6 confirmed. - spring-retry 2.0.12 as direct dep in embabel-agent-api. - spring-boot-starter-aop → aspectjweaver direct dep (Boot 4 renamed starter). - jackson-module-kotlin / jackson-dataformat-yaml groupIds migrated.
…son 3 Brings the agent platform stack onto the Spring Boot 4 line. Cascades through Spring Framework 7, Spring AI 2.0.0-M8, Jackson 3 (tools.jackson.*), Kotlin 2.2.21 (K2), and JUnit 6. Spring AI 2.0 API changes: - ChatClient.options() now takes ChatOptions.Builder<*>; bake chatOptions into the Prompt itself (preserves the ToolCallingChatOptions subtype through the advisor chain) and embed toolCallbacks via ToolCallingChatOptions.Builder so they survive the chatModel-defaults merge in addition to the spec-level .toolCallbacks() call. - Generation.getResult() / Message.getText() are now nullable; added the required !! / ?: dereferences at call sites. - Usage is non-null in 2.0; updated test mocks accordingly. - StructuredOutputConverter added getJsonSchema(); JacksonOutputConverter exposes it via a private val. - MCP customizer unified: McpSyncClientCustomizer + McpAsyncClientCustomizer → McpClientCustomizer. - MCP clientCapabilities is now non-null in test mocks. - ModelOptionsUtils.jsonToMap removed; replaced with objectMapper.readValue. Jackson 3 migration (tools.jackson.*): - POM groupIds: com.fasterxml.jackson.module/dataformat → tools.jackson.*; spring-boot pulls both jackson-bom (2.x) and tools.jackson:jackson-bom (3.x). - jackson-datatype-jsr310 removed — JavaTimeModule is built into Jackson 3. - ObjectMapper is now immutable; JsonMapper.builder() / rebuild() pattern for lenientMapper customization. - ValueDeserializer (was JsonDeserializer); ContextualDeserializer merged in. - propertyName / propertyNames (was fieldName / fieldNames). - WRITE_DATES_AS_TIMESTAMPS relocated to DateTimeFeature. - Custom MaybeReturnDeserializer rewritten against the Jackson 3 API. - Jackson 3 throws IllegalArgumentException/JacksonException (was IOException) for unserializable graphs; loosened test assertions accordingly. Spring Boot 4: - Jackson2ObjectMapperBuilder is no longer auto-configured; embabelJackson- ObjectMapper now builds via jacksonObjectMapper() directly and is autowire-eligible (dropped defaultCandidate=false) so generic ObjectMapper injections in integration tests resolve. - spring-retry was removed from the Boot 4 BOM but the API we use is unchanged; kept the library as a direct dep (spring-retry 2.0.12) rather than migrating to org.springframework.core.retry. - @AutoConfigureMockMvc moved to the new spring-boot-webmvc-test artifact under a different package; removed from CustomValidationAnnotationTest since it didn't actually use MockMvc. Spring Framework 7 / Kotlin 2.2.21 / JSpecify: - @NullMarked enforcement on Spring AI / Spring core / Jackson 3 supertypes cascades T : Any bounds into our overrides. Added -Xjspecify-annotations= ignore to embabel-build to suppress JSpecify-derived bound errors and reverted most <T : Any> bound additions, keeping them only at the unavoidable boundary (7 converter classes that directly extend Spring AI's StructuredOutputConverter / Spring's ObjectProvider). - Cast outputClass to Class<Any> at 4 converter-construction sites so unbounded <O> enclosing methods can still construct the bounded converters. - AutoRegistration ApplicationListener<ContextRefreshedEvent> bound dropped the redundant ? per Spring 7's stricter signatures. ArchUnit / victools / Jackson 3 schema generation: - victools 5.0.0 (Jackson 3 native) pulled transitively by Spring AI 2.0. - ObjectNode.deepCopy() returns ObjectNode directly (no type arg). - Schema "required" field may now nest arrays; flattened in two test sites. Tests: - FakeChatModel defaults switched from DefaultChatOptions to ToolCallingChatOptions so the prompt.options merge preserves the subtype. - 3 assertions on prompt.options.toolCallbacks count relaxed — Spring AI 2.0 routes spec toolCallbacks through ToolCallAdvisor internally rather than mirroring them onto the final prompt seen by ChatModel.call(). - assertThrows<X?> → assertThrows<X> (JUnit 6 @NullMarked). - Many test helpers bounded <T : Any> to match migrated main-source signatures. POM: - kotlin.version 2.1.10 → 2.2.21; kotlin.compiler.apiVersion 2.1 → 2.2. - spring-boot.version 4.0.6 confirmed. - spring-retry 2.0.12 as direct dep in embabel-agent-api. - spring-boot-starter-aop → aspectjweaver direct dep (Boot 4 renamed starter). - jackson-module-kotlin / jackson-dataformat-yaml groupIds migrated.
…customizer - A2A: add spring-boot-webmvc-test test dep; @AutoConfigureMockMvc moved to org.springframework.boot.webmvc.test.autoconfigure - Replace McpSyncClientCustomizer/McpAsyncClientCustomizer (Spring AI 1.x) with unified McpClientCustomizer (Spring AI 2.0) in javadoc refs
…odules - bedrock: JsonMapper for Spring AI 2.0; spring-boot-jackson test dep (JacksonAutoConfiguration relocated to o.s.b.jackson.autoconfigure) - observability: ContentCachingRequestWrapper 2-arg ctor (prod + 3 tests); ObservationRegistryCustomizer moved to micrometer-observation module - shell: javax.validation -> jakarta.validation imports - mcpserver-security: spring-boot-security + oauth2 resource-server test deps; SecurityAutoConfiguration FQN fix for Boot 4 split - mcpserver: McpSchema.Resource ctor gained title/size/meta params - webmvc: spring-boot-webmvc-test dep; MockMvc import relocation (5 tests) - deepseek/google-genai/mistral-ai: drop redundant in-builder retryTemplate call (Spring AI 2.0 expects o.s.core.retry, retries already wrap at ChatClientLlmOperations via spring-retry) - reactor: temporarily disable embabel-agent-openai and the autoconfigure/ starter modules transitively depending on it (openai*, openai-custom*, anthropic*, lmstudio*, gemini*, dockermodels*, minimax*) pending Spring AI 2.0 rewrites — OpenAiApi/AnthropicApi were removed in M8
…native SDKs Spring AI 2.0.0-M8 removed its hand-rolled OpenAiApi / AnthropicApi facades and delegates to the official openai-java (OpenAIClient) and anthropic-java (AnthropicClient) SDKs. The model builders' fluent setters were renamed (.openAiApi -> .openAiClient, .anthropicApi -> .anthropicClient, .defaultOptions -> .options) and .retryTemplate(spring-retry RetryTemplate) was dropped — retries already wrap at the ChatClientLlmOperations layer. OpenAI: - OpenAiCompatibleModelFactory: build OpenAIClient via OpenAIOkHttpClient builder (baseUrl, apiKey, customHeaders); ctor preserves restClientBuilder / webClientBuilder / completionsPath / embeddingsPath / retryTemplate params as no-ops for source compatibility with the 5 downstream subclasses (LMStudio, Gemini, Minimax, OpenAi-custom, OpenAi-autoconfigure). - OpenAiEmbeddingModel switched to the (OpenAIClient, MetadataMode, Options, ObservationRegistry) ctor. - DockerLocalModelsConfig: same migration off the now-removed OpenAiApi. - embabel-agent-openai pom: pin openai-java + openai-java-client-okhttp 4.36.0 at compile scope (overriding the BOM's 4.16.1/test) and add spring-webflux (spring-ai-openai 2.0 dropped its webflux dep but our factory's ctor still types webClientBuilder against WebClient.Builder). - LLMOpenAiGuardRailsIntegrationIT: rewire OpenAiModerationModel via OpenAiModerationModel.builder().openAiClient(...) — OpenAiModerationApi no longer exists. Anthropic: - AnthropicModelFactory: build AnthropicClient via AnthropicOkHttpClient builder (preferred over AnthropicSetup.setupSyncClient to avoid the SDK's implicit ANTHROPIC_BASE_URL / ANTHROPIC_API_KEY env-var precedence). - AnthropicCacheTtl / AnthropicCacheOptions / AnthropicCacheStrategy promoted out of the .api subpackage in Spring AI 2.0; update imports. - Thinking config: AnthropicApi.ChatCompletionRequest.ThinkingConfig is gone — use first-class AnthropicChatOptions.Builder methods thinkingEnabled(long) / thinkingDisabled(). - UsageExtensions: AnthropicApi.Usage (int accessors) -> anthropic-java's com.anthropic.models.messages.Usage (Optional<Long> accessors). Preserve Int? return shape via .orElse(null)?.toInt(). - Test fixtures rewritten: ThinkingConfigParam exposes isEnabled() / isDisabled() as functions (not properties); UsageExtensionsTest gets a helper that wraps Usage.builder() to keep the prior positional ergonomics. Reactor: re-enable embabel-agent-openai + the seven autoconfigure/starter modules disabled in the previous commit pending these rewrites (openai, openai-custom, anthropic, lmstudio, gemini, dockermodels, minimax). Plus a small observability follow-up: gate MicrometerTracingAutoConfiguration's defaultTracingObservationHandler with @ConditionalOnBean(Tracer.class) — the bean used Tracer as a hard ctor param and crashed app startup whenever no tracing bridge (Brave / OTel) was wired in.
|
do not merge this one. It's for information purposes only. |
Spring Boot 4 / Spring AI 2.0 brought Jackson 3 (tools.jackson.*). The Spring context now publishes a tools.jackson.databind.ObjectMapper bean — autowiring the Jackson 2 com.fasterxml.jackson.databind.ObjectMapper fails with NoSuchBeanDefinition. Update the import; the readValue/writeValueAsString call sites work unchanged.
Spring Boot 4 split JacksonAutoConfiguration into its own module (spring-boot-jackson). The test's slim @SpringBootTest(classes=[…]) bootstrap doesn't import it, so neither a Jackson 2 nor Jackson 3 ObjectMapper bean is available to autowire. The mapper is only used for writeValueAsString / readValue on test DTOs — drop the @Autowired and construct it inline via jacksonObjectMapper() from tools.jackson.module.kotlin.
Same Jackson 2 → 3 migration applied earlier in examples-common: switch the com.fasterxml.jackson.module.kotlin imports to tools.jackson.module.kotlin, and collapse ObjectMapper().registerKotlinModule() to jacksonObjectMapper() (Jackson 3's ObjectMapper is immutable, so the fluent-register pattern is gone — the helper returns a mapper with the Kotlin module already wired).
poutsma
left a comment
There was a problem hiding this comment.
Well done, @alexheifetz. that must have been an enormous effort.
Looks good from my end, the only minor comment I have is that some commits include unnecessary space removals that muck up the git history. I have indicated where I have noticed them.
|
|
||
| // Execution methods | ||
| fun <T> createObject( | ||
| fun <T>createObject( |
There was a problem hiding this comment.
Minor nitpick: perhaps revert this and the next three space removals to keep the git history clean.
There was a problem hiding this comment.
Good catch — thanks. These came from an IDE reformat that dropped the space after the type-parameter list (fun name → fun name). Reverted all 61 occurrences across 9 files, so the generic-method spacing is back to the original style everywhere.
| * @return creating mode supporting examples, property filtering, and validation | ||
| */ | ||
| fun <T> creating(outputClass: Class<T>): Creating<T> | ||
| fun <T>creating(outputClass: Class<T>): Creating<T> |
|
|
||
| val innerToolsByName = innerTools.associateBy { it.definition.name } | ||
| for (fieldName in parsed.fieldNames()) { | ||
| for (fieldName in parsed.propertyNames()) { |
There was a problem hiding this comment.
Let's rename the variable to propertyName here.
| } | ||
|
|
||
| override fun <O> createObjectStream( | ||
| override fun <O>createObjectStream( |
| } | ||
|
|
||
| override fun <O> createObjectStream( | ||
| override fun <O>createObjectStream( |
| * @throws RuntimeException if the operation times out or fails | ||
| */ | ||
| protected fun <T> executeWithTimeout( | ||
| protected fun <T>executeWithTimeout( |
| ) { | ||
|
|
||
| override fun <O> doTransform( | ||
| override fun <O>doTransform( |
| override fun withToolChainingFromAny(): PromptExecutionDelegate = this | ||
|
|
||
| override fun <T> createObject(messages: List<Message>, outputClass: Class<T>): T { | ||
| override fun <T>createObject(messages: List<Message>, outputClass: Class<T>): T { |
| * Extension of [JacksonOutputConverter] that allows for filtering of properties of the generated object via a predicate. | ||
| */ | ||
| open class FilteringJacksonOutputConverter<T> internal constructor( | ||
| open class FilteringJacksonOutputConverter<T : Any>( |
There was a problem hiding this comment.
Why was internal constructor removed?
There was a problem hiding this comment.
Unintentional — it got dropped during the migration. Restored internal constructor on the primary constructor; the bound is required by the parent JacksonOutputConverter so I kept that.
|
|
from CLAUDE: The code changes are high quality:
|
Spring AI relocated AnthropicCacheTtl out of the .anthropic.api package into .anthropic. Update the test import from org.springframework.ai.anthropic.api.AnthropicCacheTtl to org.springframework.ai.anthropic.AnthropicCacheTtl. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Apache license header had its "Copyright 2024-2026 Embabel Pty Ltd." line (and trailing blank) repeated twice at the top of the file. Drop the duplicate so the header matches the standard single-block form. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Spring AI 2.0 reshaped the ToolCallingChatOptions interface: the set* mutators (setToolCallbacks/setToolNames/setToolContext/ setInternalToolExecutionEnabled) were dropped in favour of builder-based configuration, and a new abstract mutate() returning ToolCallingChatOptions.Builder<*> was added. - Drop the `override` from the four tool setters; they remain as plain helpers used internally by merge() and the builder. - Implement mutate() to return a builder seeded with copy(), preserving the OCI-specific fields (compartmentId, servingMode, endpointId, apiFormat) alongside the standard chat/tool options. - Make the nested Builder implement ToolCallingChatOptions.Builder<Builder>, adding the now-required members: toolCallbacks/toolNames/toolContext (collection + vararg/pair overloads), plus clone() and combineWith() from ChatOptions.Builder. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The test wrapped the parallel map in assertTimeoutPreemptively(300ms) to prove execution wasn't serial (serial = 8 × 100ms = 800ms; parallel ≈ 200ms). With only ~100ms of slack over the ideal, GC/scheduling on loaded CI runners pushed it past 300ms and it flaked (Run 1 timeout, Run 2 pass), failing the build under failOnFlakeCount=1. The maxConcurrent >= concurrencyLevel assertion already proves parallelism deterministically: each task records the peak number of simultaneously sleeping tasks, which can only reach the concurrency level under genuine parallel execution (serial would peak at 1). Drop the redundant timing- based timeout and rely on that assertion; remove the now-unused assertTimeoutPreemptively / Duration imports. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- UnfoldingTool: rename loop variable `fieldName` -> `propertyName` in tryShortcutDispatch to match the Jackson 3 fieldNames() -> propertyNames() migration. - FilteringJacksonOutputConverter: restore the `internal constructor` modifier on the primary constructor (unintentionally dropped during the migration). The `<T : Any>` bound is required by the parent and is retained; all callers use the public secondary constructors. - Revert spurious `fun <T> name` -> `fun <T>name` spacing changes across embabel-agent-api (61 sites in 9 files) to keep the git history clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…eSender Spring AI 2.0 made ToolCallingChatOptions.toolCallbacks and internalToolExecutionEnabled read-only, so the migration commented out the setters and returned a bare copy(). That silently dropped the tool callbacks whenever chatOptions was already a ToolCallingChatOptions (e.g. Anthropic / OpenAI provider options), breaking tool calling such as vector/fulltext search. Use mutate() to derive a new instance with the callbacks attached and Spring AI's automatic tool execution disabled, preserving the provider-specific subtype. This matches the pattern already used in ChatClientLlmOperations and SpringAiLlmMessageStreamer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Embabel's MicrometerTracingAutoConfiguration registers a NonEmbabelTracingObservationHandler (a DefaultTracingObservationHandler subclass) guarded by @ConditionalOnMissingBean. Spring Boot's own tracing auto-config registers a DefaultTracingObservationHandler with the same condition, so whichever runs first wins — the ordering was undefined. Make the ordering deterministic via @autoConfiguration: - afterName OpenTelemetryTracingAutoConfiguration: run after the OpenTelemetry Tracer (OtelTracer) bean exists, otherwise @ConditionalOnBean(Tracer.class) evaluates false and our handler is never registered. In Spring Boot 4 the Tracer is produced by a different class than the handler registrar, so a single beforeName is not enough. - beforeName MicrometerTracingAutoConfiguration: run before Boot registers its DefaultTracingObservationHandler, so Boot's @ConditionalOnMissingBean backs off in favour of ours. Boot's classes are referenced by name so we take no compile/runtime dependency on the spring-boot-micrometer-tracing(-opentelemetry) modules; the ordering is ignored when those modules are absent from the classpath. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Yes, the amount of code changes (mostly related to Jackson 3 upgrade) is significant, but needs to be done in order to move the project forward :) |
|
I noticed when migrating a small embabel example to embabel 2.0.0-SNAPSHOT that the current 2.0.0 branch still uses spring shell 3.x. This still seems to work but to be compatible with spring boot 4 you should also upgrade to spring shell 4.x. Unfortunately the annotations you used are no longer supported in 4.x and have to be replaced as described in the upgrade guide. |
…pring AI 2/Jackson 3 Resolves conflicts and forward-ports HEAD's native-structured-output + JSON schema features onto the 2.0.0 baseline (Spring Boot 4, Spring AI 2.0.0-M8, Jackson 3). The merge text-merged cleanly but the incoming feature code was written against pre-2.0 APIs, so each affected file was ported, not just merged. Conflict resolutions: - ChatClientLlmOperations: keep 2.0.0's Class<Any> erasure (Spring AI 2.0 requires T : Any); re-wire the JSON converter through the adapter's jsonSchemaProvider so native structured output (#1715) survives the merge - JacksonOutputConverter / converters: jsonSchema exposed as fun getJsonSchema() (property form clashes with Spring AI 2.0 StructuredOutputConverter.getJsonSchema()) Jackson 2 -> Jackson 3 (com.fasterxml.jackson -> tools.jackson): - jsonSchemaSupport, nativeStructuredOutputSupport, OpenAiNativeStructuredOutputConfigurer and tests migrated to tools.jackson APIs - fieldNames() -> propertyNames(), elements() -> values(), ObjectMapper() -> JsonMapper.builder(), ObjectNode.set<T>() -> set(), and SerializationConfig.introspect() -> ClassIntrospector chain (introspectClassAnnotations + introspectForSerialization) Spring AI 1.x -> 2.0 (OpenAI native structured output): - ResponseFormat moved to OpenAiChatModel.ResponseFormat; jsonSchema now takes a String - options configured via mutate() builder (responseFormat/outputSchema are read-only) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sync 2.0.0-061326 with 2.0.0: port native structured output to SB4 / Spring AI 2 / Jackson 3
Adapt code from Spring AI 2.0.0-M8 to 2.0.0 GA after the merge in 90d0e1e. - JacksonOutputConverter: LoggingMarkers removed in GA -> SLF4J MarkerFactory.getMarker("SENSITIVE") - SpringAiLlmMessageSender: drop removed per-request internalToolExecutionEnabled flag (internal tool execution is now controlled at the ChatModel level) - ChatClientLlmTransformerTest: DefaultChatOptions() ctor now protected -> ChatOptions.builder().build() - Bedrock: drop removed ToolExecutionEligibilityPredicate (use 5-arg BedrockProxyChatModel ctor); convert Cohere Properties.Options -> BedrockCohereEmbeddingOptions Build state: core modules + Bedrock compile. Remaining provider modules (Anthropic, Gemini, OCI, etc.) still need the same GA migration. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
OllamaChatModel/OllamaEmbeddingModel builders renamed defaultOptions() -> options() in Spring AI 2.0. Update both call sites in OllamaModelsConfig. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ChatModel builders renamed defaultOptions() -> options() in Spring AI 2.0. Update DeepSeekModelsConfig and MistralAiModelsConfig. (Bedrocks .defaultOptions is on embabels own EmbabelBedrockProxyChatModelBuilder and is intentionally unchanged.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Spring AI 2.0.0 moved GoogleGenAiEmbeddingConnectionDetails to the org.springframework.ai.google.genai.embedding sub-package. Update the import in GoogleGenAiModelsConfig. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
OciGenAiChatOptions hand-implements Spring AI options interfaces, which changed in 2.0.0: - ToolCallingChatOptions dropped toolNames + internalToolExecutionEnabled; ChatOptions dropped copy(). Drop override on these (getters, builder methods, copy) and keep them as OCI-internal members. - merge(): stop reading toolNames/internalToolExecutionEnabled off the Spring AI ToolCallingChatOptions interface; merge them only between OciGenAiChatOptions instances. - Test: call getInternalToolExecutionEnabled() explicitly (property name now resolves to the private backing var). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Spring AI 2.0 GA ChatClient no longer preserves the ToolCallingChatOptions subtype through its option merge; a real ChatModel now receives a plain ChatOptions (tools flow via the ToolCallingAdvisor / spec-level toolCallbacks). The test fakes asserted prompt.options is ToolCallingChatOptions, which held in M8 but not GA. - FakeChatModel and the streaming guardrail fake now accept any ChatOptions instead of throwing. - optionsPassed typed as List<ChatOptions>; the "presents no tools" assertion reads toolCallbacks null-safe via an as? cast (also handles getToolCallbacks() now returning null when empty). - Removed a dead options assertion in the delaying fake. Test-only; no production change. Resolves the 11 failures in ChatClientLlmOperationsTest / ChatClientLlmOperationsThinkingTest / StreamingChatClientOperationsGuardRailTest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ng AI 2.0) Spring AI 2.0 spring-ai-anthropic depends only on anthropic-java-core, not the OkHttp client. AnthropicModelFactory uses AnthropicOkHttpClient directly, so the module must declare anthropic-java-client-okhttp explicitly. Version is supplied by the embabel-build BOM (anthropic-java.version) - no inline version here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nsDetails anthropic-java 2.40.1 (pinned transitively by spring-ai-anthropic 2.0.0) made Usage.Builder.outputTokensDetails a required field. The anthropicUsage test helper did not set it, so Usage.build() threw IllegalStateException on all 12 tests. Set it to Optional.empty(), consistent with the helpers other required-but-empty fields. Test-only. (Surfaced only on CI: local .m2 still had anthropic-java 2.34.0 and the module was built with -DskipTests.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Spring AI 2.0.0 GA Migration
Synchronize with 1.0 06222026
|



This pull request updates the codebase to support Spring Boot 4 and the new
tools.jacksonpackage, and makes related dependency and code changes. The main themes are migration fromcom.fasterxml.jacksontotools.jackson, updating dependencies for Spring Boot 4 compatibility, and minor API improvements.Migration to tools.jackson:
com.fasterxml.jackson.databind.*,com.fasterxml.jackson.module.*, andcom.fasterxml.jackson.dataformat.*with theirtools.jacksonequivalents across main and test sources, includingObjectMapper,JsonDeserialize, and YAML handling (YAMLMapperandkotlinModule). [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19]Spring Boot 4 and dependency updates:
pom.xmlfiles from0.5.0-SNAPSHOTto2.0.0-SNAPSHOTto reflect the new release and Spring Boot 4 compatibility. [1] [2]spring-boot-webmvc-testdependency for MockMvc support, and updated the test annotation import toorg.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvcfor Spring Boot 4. [1] [2]spring-retry(version 2.0.12) since it is no longer managed by the Spring Boot BOM. [1] [2]Code and API improvements:
withPropertiesandwithoutPropertiesextension functions to useKProperty1<T, *>for better Kotlin compatibility. [1] [2].findAndRegisterModules()call onjacksonObjectMapper()in test code.These changes ensure compatibility with Spring Boot 4, migrate to the new Jackson package, and improve type safety and maintainability.