From 21501a9a15c4b97591c9b81ef7922a70dcad08c2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 14:48:07 +0000 Subject: [PATCH 1/7] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 766c6aef..9d37c7df 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 136 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-64c3a646eb5dcad2b7ff7bd976c0e312b886676a542f6ffcd9a6c8503ae24c58.yml openapi_spec_hash: 91b1b7bf3c1a6b6c9c7507d4cac8fe2a -config_hash: f8e6baff429cf000b8e4ba1da08dff47 +config_hash: e7976c555732f55dc92f3aa09558ef9d From 1823ecab53fd72ef7f7fdc7776e6ecd631307f7c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:02:06 +0000 Subject: [PATCH 2/7] feat(api): add webhook signature verification --- .../services/async/WebhookServiceAsyncTest.kt | 30 ++++++++++++++++ .../services/blocking/WebhookServiceTest.kt | 34 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 openai-java-core/src/test/kotlin/com/openai/services/async/WebhookServiceAsyncTest.kt diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/WebhookServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/WebhookServiceAsyncTest.kt new file mode 100644 index 00000000..255b0231 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/WebhookServiceAsyncTest.kt @@ -0,0 +1,30 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.async + +import com.openai.TestServerExtension +import com.openai.client.okhttp.OpenAIOkHttpClientAsync +import com.openai.core.http.Headers +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class WebhookServiceAsyncTest { + + @Test + fun unwrap() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val webhookServiceAsync = client.webhooks() + + val payload = + "{\"id\":\"id\",\"created_at\":0,\"data\":{\"id\":\"id\"},\"type\":\"batch.cancelled\",\"object\":\"event\"}" + val webhookSecret = "whsec_c2VjcmV0Cg==" + val headers = Headers.builder().build() + + webhookServiceAsync.unwrap(payload).validate() + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/WebhookServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/WebhookServiceTest.kt index 3b20eba4..6938c9c3 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/blocking/WebhookServiceTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/WebhookServiceTest.kt @@ -1,3 +1,4 @@ +<<<<<<< HEAD // File generated from our OpenAPI spec by Stainless. package com.openai.services.blocking @@ -226,3 +227,36 @@ internal class WebhookServiceTest { } } } +||||||| parent of 8235a47f (feat(api): add webhook signature verification) +======= +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.blocking + +import com.openai.TestServerExtension +import com.openai.client.okhttp.OpenAIOkHttpClient +import com.openai.core.http.Headers +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class WebhookServiceTest { + + @Test + fun unwrap() { + val client = + OpenAIOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val webhookService = client.webhooks() + + val payload = + "{\"id\":\"id\",\"created_at\":0,\"data\":{\"id\":\"id\"},\"type\":\"batch.cancelled\",\"object\":\"event\"}" + val webhookSecret = "whsec_c2VjcmV0Cg==" + val headers = Headers.builder().build() + + webhookService.unwrap(payload).validate() + } +} +>>>>>>> 8235a47f (feat(api): add webhook signature verification) From 5c017872b071272eff021318dab9a4a774cfcd4c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:58:44 +0000 Subject: [PATCH 3/7] chore(internal): upgrade AssertJ --- openai-java-client-okhttp/build.gradle.kts | 2 +- openai-java-core/build.gradle.kts | 2 +- openai-java-proguard-test/build.gradle.kts | 2 +- openai-java-spring-boot-starter/build.gradle.kts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openai-java-client-okhttp/build.gradle.kts b/openai-java-client-okhttp/build.gradle.kts index 272eaba2..753e4fbe 100644 --- a/openai-java-client-okhttp/build.gradle.kts +++ b/openai-java-client-okhttp/build.gradle.kts @@ -10,6 +10,6 @@ dependencies { implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") testImplementation(kotlin("test")) - testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("org.assertj:assertj-core:3.27.7") testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2") } diff --git a/openai-java-core/build.gradle.kts b/openai-java-core/build.gradle.kts index ec4a8ca2..cddd7776 100644 --- a/openai-java-core/build.gradle.kts +++ b/openai-java-core/build.gradle.kts @@ -38,7 +38,7 @@ dependencies { testImplementation(kotlin("test")) testImplementation(project(":openai-java-client-okhttp")) testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2") - testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("org.assertj:assertj-core:3.27.7") testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.3") testImplementation("org.junit-pioneer:junit-pioneer:1.9.1") diff --git a/openai-java-proguard-test/build.gradle.kts b/openai-java-proguard-test/build.gradle.kts index 43c01fbd..b37b7c45 100644 --- a/openai-java-proguard-test/build.gradle.kts +++ b/openai-java-proguard-test/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { testImplementation(project(":openai-java")) testImplementation(kotlin("test")) testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") - testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("org.assertj:assertj-core:3.27.7") testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") } diff --git a/openai-java-spring-boot-starter/build.gradle.kts b/openai-java-spring-boot-starter/build.gradle.kts index 20c06d07..fcf71dfe 100644 --- a/openai-java-spring-boot-starter/build.gradle.kts +++ b/openai-java-spring-boot-starter/build.gradle.kts @@ -13,5 +13,5 @@ dependencies { annotationProcessor("org.springframework.boot:spring-boot-configuration-processor:2.7.18") testImplementation("org.springframework.boot:spring-boot-starter-test:2.7.18") - testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("org.assertj:assertj-core:3.27.7") } From da0fb59b0e0362ee68353829c97ac8b2944cd49b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:33:23 +0000 Subject: [PATCH 4/7] feat(api): add context_management to responses --- .../StructuredResponseCreateParams.kt | 22 +++++++++++++++++++ .../StructuredResponseCreateParamsTest.kt | 6 +++++ 2 files changed, 28 insertions(+) diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponseCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponseCreateParams.kt index 563b6ae9..0eb7a666 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponseCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponseCreateParams.kt @@ -116,6 +116,28 @@ class StructuredResponseCreateParams( paramsBuilder.background(background) } + /** @see ResponseCreateParams.Builder.contextManagement */ + fun contextManagement(contextManagement: List?) = + apply { + paramsBuilder.contextManagement(contextManagement) + } + + /** @see ResponseCreateParams.Builder.contextManagement */ + fun contextManagement( + contextManagement: Optional> + ) = apply { paramsBuilder.contextManagement(contextManagement) } + + /** @see ResponseCreateParams.Builder.contextManagement */ + fun contextManagement( + contextManagement: JsonField> + ) = apply { paramsBuilder.contextManagement(contextManagement) } + + /** @see ResponseCreateParams.Builder.addContextManagement */ + fun addContextManagement(contextManagement: ResponseCreateParams.ContextManagement) = + apply { + paramsBuilder.addContextManagement(contextManagement) + } + /** @see ResponseCreateParams.Builder.conversation */ fun conversation(conversation: ResponseCreateParams.Conversation?) = apply { paramsBuilder.conversation(conversation) diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseCreateParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseCreateParamsTest.kt index 10713629..3c909af7 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseCreateParamsTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseCreateParamsTest.kt @@ -65,6 +65,8 @@ internal class StructuredResponseCreateParamsTest { private val RESPONSE_CONVERSATION_PARAM = ResponseConversationParam.builder().id(STRING).build() private val CONVERSATION = ResponseCreateParams.Conversation.ofId(STRING) + private val CONTEXT_MANAGEMENT = + ResponseCreateParams.ContextManagement.builder().type(STRING).build() private val PROMPT_CACHE_RETENTION = ResponseCreateParams.PromptCacheRetention.IN_MEMORY private val PROMPT_CACHE_RETENTION_OPTIONAL = Optional.of(PROMPT_CACHE_RETENTION) private val PROMPT_CACHE_RETENTION_JSON_FIELD = JsonField.of(PROMPT_CACHE_RETENTION) @@ -136,6 +138,10 @@ internal class StructuredResponseCreateParamsTest { DelegationWriteTestCase("background", BOOLEAN), DelegationWriteTestCase("background", OPTIONAL), DelegationWriteTestCase("background", JSON_FIELD), + DelegationWriteTestCase("contextManagement", LIST), + DelegationWriteTestCase("contextManagement", OPTIONAL), + DelegationWriteTestCase("contextManagement", JSON_FIELD), + DelegationWriteTestCase("addContextManagement", CONTEXT_MANAGEMENT), DelegationWriteTestCase("conversation", CONVERSATION), DelegationWriteTestCase("conversation", OPTIONAL), DelegationWriteTestCase("conversation", JSON_FIELD), From c0f2cd1c854d6fca90c9000de46f042e64a8cbf5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 8 Feb 2026 20:49:02 +0000 Subject: [PATCH 5/7] feat(api): responses context_management --- .stats.yml | 6 +- .../openai/models/images/ImageEditParams.kt | 24 +- .../models/responses/ResponseCreateParams.kt | 334 +++++++++++++++++- .../com/openai/models/responses/Tool.kt | 14 +- .../responses/ResponseCreateParamsTest.kt | 19 + .../async/ResponseServiceAsyncTest.kt | 12 + .../services/blocking/ResponseServiceTest.kt | 12 + 7 files changed, 400 insertions(+), 21 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9d37c7df..10450956 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 136 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-64c3a646eb5dcad2b7ff7bd976c0e312b886676a542f6ffcd9a6c8503ae24c58.yml -openapi_spec_hash: 91b1b7bf3c1a6b6c9c7507d4cac8fe2a -config_hash: e7976c555732f55dc92f3aa09558ef9d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-bff810f46da56eff8d5e189b0d1f56ac07a8289723666138549d4239cad7c2ea.yml +openapi_spec_hash: 7532ce5a6f490c8f5d1e079c76c70535 +config_hash: a1454ffd9612dee11f9d5a98e55eac9e diff --git a/openai-java-core/src/main/kotlin/com/openai/models/images/ImageEditParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/images/ImageEditParams.kt index 9b1799cb..e836c56b 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/images/ImageEditParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/images/ImageEditParams.kt @@ -82,8 +82,9 @@ private constructor( /** * Control how much effort the model will exert to match the style and features, especially - * facial features, of input images. This parameter is only supported for `gpt-image-1`. - * Unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. + * facial features, of input images. This parameter is only supported for `gpt-image-1` and + * `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and + * `low`. Defaults to `low`. * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -438,8 +439,9 @@ private constructor( /** * Control how much effort the model will exert to match the style and features, especially - * facial features, of input images. This parameter is only supported for `gpt-image-1`. - * Unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. + * facial features, of input images. This parameter is only supported for `gpt-image-1` and + * `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and + * `low`. Defaults to `low`. */ fun inputFidelity(inputFidelity: InputFidelity?) = apply { body.inputFidelity(inputFidelity) @@ -917,8 +919,9 @@ private constructor( /** * Control how much effort the model will exert to match the style and features, especially - * facial features, of input images. This parameter is only supported for `gpt-image-1`. - * Unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. + * facial features, of input images. This parameter is only supported for `gpt-image-1` and + * `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and + * `low`. Defaults to `low`. * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -1319,8 +1322,8 @@ private constructor( /** * Control how much effort the model will exert to match the style and features, * especially facial features, of input images. This parameter is only supported for - * `gpt-image-1`. Unsupported for `gpt-image-1-mini`. Supports `high` and `low`. - * Defaults to `low`. + * `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for + * `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. */ fun inputFidelity(inputFidelity: InputFidelity?) = inputFidelity(MultipartField.of(inputFidelity)) @@ -2005,8 +2008,9 @@ private constructor( /** * Control how much effort the model will exert to match the style and features, especially - * facial features, of input images. This parameter is only supported for `gpt-image-1`. - * Unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. + * facial features, of input images. This parameter is only supported for `gpt-image-1` and + * `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and + * `low`. Defaults to `low`. */ class InputFidelity @JsonCreator private constructor(private val value: JsonField) : Enum { diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseCreateParams.kt index 834f54a4..c08c2277 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseCreateParams.kt @@ -24,6 +24,7 @@ import com.openai.core.JsonValue import com.openai.core.Params import com.openai.core.allMaxBy import com.openai.core.checkKnown +import com.openai.core.checkRequired import com.openai.core.getOrThrow import com.openai.core.http.Headers import com.openai.core.http.QueryParams @@ -65,6 +66,14 @@ private constructor( */ fun background(): Optional = body.background() + /** + * Context management configuration for this request. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun contextManagement(): Optional> = body.contextManagement() + /** * The conversation that this response belongs to. Items from this conversation are prepended to * `input_items` for this response request. Input items and output items from this response are @@ -378,6 +387,14 @@ private constructor( */ fun _background(): JsonField = body._background() + /** + * Returns the raw JSON value of [contextManagement]. + * + * Unlike [contextManagement], this method doesn't throw if the JSON field has an unexpected + * type. + */ + fun _contextManagement(): JsonField> = body._contextManagement() + /** * Returns the raw JSON value of [conversation]. * @@ -602,10 +619,10 @@ private constructor( * This is generally only useful if you are already constructing the body separately. * Otherwise, it's more convenient to use the top-level setters instead: * - [background] + * - [contextManagement] * - [conversation] * - [include] * - [input] - * - [instructions] * - etc. */ fun body(body: Body) = apply { this.body = body.toBuilder() } @@ -635,6 +652,35 @@ private constructor( */ fun background(background: JsonField) = apply { body.background(background) } + /** Context management configuration for this request. */ + fun contextManagement(contextManagement: List?) = apply { + body.contextManagement(contextManagement) + } + + /** Alias for calling [Builder.contextManagement] with `contextManagement.orElse(null)`. */ + fun contextManagement(contextManagement: Optional>) = + contextManagement(contextManagement.getOrNull()) + + /** + * Sets [Builder.contextManagement] to an arbitrary JSON value. + * + * You should usually call [Builder.contextManagement] with a well-typed + * `List` value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun contextManagement(contextManagement: JsonField>) = apply { + body.contextManagement(contextManagement) + } + + /** + * Adds a single [ContextManagement] to [Builder.contextManagement]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addContextManagement(contextManagement: ContextManagement) = apply { + body.addContextManagement(contextManagement) + } + /** * The conversation that this response belongs to. Items from this conversation are * prepended to `input_items` for this response request. Input items and output items from @@ -1595,6 +1641,7 @@ private constructor( @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val background: JsonField, + private val contextManagement: JsonField>, private val conversation: JsonField, private val include: JsonField>, private val input: JsonField, @@ -1629,6 +1676,9 @@ private constructor( @JsonProperty("background") @ExcludeMissing background: JsonField = JsonMissing.of(), + @JsonProperty("context_management") + @ExcludeMissing + contextManagement: JsonField> = JsonMissing.of(), @JsonProperty("conversation") @ExcludeMissing conversation: JsonField = JsonMissing.of(), @@ -1699,6 +1749,7 @@ private constructor( @JsonProperty("user") @ExcludeMissing user: JsonField = JsonMissing.of(), ) : this( background, + contextManagement, conversation, include, input, @@ -1737,6 +1788,15 @@ private constructor( */ fun background(): Optional = background.getOptional("background") + /** + * Context management configuration for this request. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun contextManagement(): Optional> = + contextManagement.getOptional("context_management") + /** * The conversation that this response belongs to. Items from this conversation are * prepended to `input_items` for this response request. Input items and output items from @@ -2058,6 +2118,16 @@ private constructor( @ExcludeMissing fun _background(): JsonField = background + /** + * Returns the raw JSON value of [contextManagement]. + * + * Unlike [contextManagement], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("context_management") + @ExcludeMissing + fun _contextManagement(): JsonField> = contextManagement + /** * Returns the raw JSON value of [conversation]. * @@ -2309,6 +2379,7 @@ private constructor( class Builder internal constructor() { private var background: JsonField = JsonMissing.of() + private var contextManagement: JsonField>? = null private var conversation: JsonField = JsonMissing.of() private var include: JsonField>? = null private var input: JsonField = JsonMissing.of() @@ -2340,6 +2411,7 @@ private constructor( @JvmSynthetic internal fun from(body: Body) = apply { background = body.background + contextManagement = body.contextManagement.map { it.toMutableList() } conversation = body.conversation include = body.include.map { it.toMutableList() } input = body.input @@ -2394,6 +2466,39 @@ private constructor( */ fun background(background: JsonField) = apply { this.background = background } + /** Context management configuration for this request. */ + fun contextManagement(contextManagement: List?) = + contextManagement(JsonField.ofNullable(contextManagement)) + + /** + * Alias for calling [Builder.contextManagement] with `contextManagement.orElse(null)`. + */ + fun contextManagement(contextManagement: Optional>) = + contextManagement(contextManagement.getOrNull()) + + /** + * Sets [Builder.contextManagement] to an arbitrary JSON value. + * + * You should usually call [Builder.contextManagement] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun contextManagement(contextManagement: JsonField>) = apply { + this.contextManagement = contextManagement.map { it.toMutableList() } + } + + /** + * Adds a single [ContextManagement] to [Builder.contextManagement]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addContextManagement(contextManagement: ContextManagement) = apply { + this.contextManagement = + (this.contextManagement ?: JsonField.of(mutableListOf())).also { + checkKnown("contextManagement", it).add(contextManagement) + } + } + /** * The conversation that this response belongs to. Items from this conversation are * prepended to `input_items` for this response request. Input items and output items @@ -3225,6 +3330,7 @@ private constructor( fun build(): Body = Body( background, + (contextManagement ?: JsonMissing.of()).map { it.toImmutable() }, conversation, (include ?: JsonMissing.of()).map { it.toImmutable() }, input, @@ -3263,6 +3369,7 @@ private constructor( } background() + contextManagement().ifPresent { it.forEach { it.validate() } } conversation().ifPresent { it.validate() } include().ifPresent { it.forEach { it.validate() } } input().ifPresent { it.validate() } @@ -3309,6 +3416,7 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (if (background.asKnown().isPresent) 1 else 0) + + (contextManagement.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (conversation.asKnown().getOrNull()?.validity() ?: 0) + (include.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (input.asKnown().getOrNull()?.validity() ?: 0) + @@ -3343,6 +3451,7 @@ private constructor( return other is Body && background == other.background && + contextManagement == other.contextManagement && conversation == other.conversation && include == other.include && input == other.input && @@ -3375,6 +3484,7 @@ private constructor( private val hashCode: Int by lazy { Objects.hash( background, + contextManagement, conversation, include, input, @@ -3408,7 +3518,227 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Body{background=$background, conversation=$conversation, include=$include, input=$input, instructions=$instructions, maxOutputTokens=$maxOutputTokens, maxToolCalls=$maxToolCalls, metadata=$metadata, model=$model, parallelToolCalls=$parallelToolCalls, previousResponseId=$previousResponseId, prompt=$prompt, promptCacheKey=$promptCacheKey, promptCacheRetention=$promptCacheRetention, reasoning=$reasoning, safetyIdentifier=$safetyIdentifier, serviceTier=$serviceTier, store=$store, streamOptions=$streamOptions, temperature=$temperature, text=$text, toolChoice=$toolChoice, tools=$tools, topLogprobs=$topLogprobs, topP=$topP, truncation=$truncation, user=$user, additionalProperties=$additionalProperties}" + "Body{background=$background, contextManagement=$contextManagement, conversation=$conversation, include=$include, input=$input, instructions=$instructions, maxOutputTokens=$maxOutputTokens, maxToolCalls=$maxToolCalls, metadata=$metadata, model=$model, parallelToolCalls=$parallelToolCalls, previousResponseId=$previousResponseId, prompt=$prompt, promptCacheKey=$promptCacheKey, promptCacheRetention=$promptCacheRetention, reasoning=$reasoning, safetyIdentifier=$safetyIdentifier, serviceTier=$serviceTier, store=$store, streamOptions=$streamOptions, temperature=$temperature, text=$text, toolChoice=$toolChoice, tools=$tools, topLogprobs=$topLogprobs, topP=$topP, truncation=$truncation, user=$user, additionalProperties=$additionalProperties}" + } + + class ContextManagement + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonField, + private val compactThreshold: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("compact_threshold") + @ExcludeMissing + compactThreshold: JsonField = JsonMissing.of(), + ) : this(type, compactThreshold, mutableMapOf()) + + /** + * The context management entry type. Currently only 'compaction' is supported. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): String = type.getRequired("type") + + /** + * Token threshold at which compaction should be triggered for this entry. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun compactThreshold(): Optional = compactThreshold.getOptional("compact_threshold") + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [compactThreshold]. + * + * Unlike [compactThreshold], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("compact_threshold") + @ExcludeMissing + fun _compactThreshold(): JsonField = compactThreshold + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [ContextManagement]. + * + * The following fields are required: + * ```java + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ContextManagement]. */ + class Builder internal constructor() { + + private var type: JsonField? = null + private var compactThreshold: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(contextManagement: ContextManagement) = apply { + type = contextManagement.type + compactThreshold = contextManagement.compactThreshold + additionalProperties = contextManagement.additionalProperties.toMutableMap() + } + + /** The context management entry type. Currently only 'compaction' is supported. */ + fun type(type: String) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonField) = apply { this.type = type } + + /** Token threshold at which compaction should be triggered for this entry. */ + fun compactThreshold(compactThreshold: Long?) = + compactThreshold(JsonField.ofNullable(compactThreshold)) + + /** + * Alias for [Builder.compactThreshold]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun compactThreshold(compactThreshold: Long) = + compactThreshold(compactThreshold as Long?) + + /** + * Alias for calling [Builder.compactThreshold] with `compactThreshold.orElse(null)`. + */ + fun compactThreshold(compactThreshold: Optional) = + compactThreshold(compactThreshold.getOrNull()) + + /** + * Sets [Builder.compactThreshold] to an arbitrary JSON value. + * + * You should usually call [Builder.compactThreshold] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun compactThreshold(compactThreshold: JsonField) = apply { + this.compactThreshold = compactThreshold + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [ContextManagement]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ContextManagement = + ContextManagement( + checkRequired("type", type), + compactThreshold, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ContextManagement = apply { + if (validated) { + return@apply + } + + type() + compactThreshold() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (type.asKnown().isPresent) 1 else 0) + + (if (compactThreshold.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ContextManagement && + type == other.type && + compactThreshold == other.compactThreshold && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(type, compactThreshold, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ContextManagement{type=$type, compactThreshold=$compactThreshold, additionalProperties=$additionalProperties}" } /** diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/Tool.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/Tool.kt index abe85bb0..7589d318 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/responses/Tool.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/Tool.kt @@ -3889,8 +3889,9 @@ private constructor( /** * Control how much effort the model will exert to match the style and features, especially - * facial features, of input images. This parameter is only supported for `gpt-image-1`. - * Unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. + * facial features, of input images. This parameter is only supported for `gpt-image-1` and + * `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and + * `low`. Defaults to `low`. * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -4161,8 +4162,8 @@ private constructor( /** * Control how much effort the model will exert to match the style and features, * especially facial features, of input images. This parameter is only supported for - * `gpt-image-1`. Unsupported for `gpt-image-1-mini`. Supports `high` and `low`. - * Defaults to `low`. + * `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for + * `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. */ fun inputFidelity(inputFidelity: InputFidelity?) = inputFidelity(JsonField.ofNullable(inputFidelity)) @@ -4689,8 +4690,9 @@ private constructor( /** * Control how much effort the model will exert to match the style and features, especially - * facial features, of input images. This parameter is only supported for `gpt-image-1`. - * Unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`. + * facial features, of input images. This parameter is only supported for `gpt-image-1` and + * `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and + * `low`. Defaults to `low`. */ class InputFidelity @JsonCreator private constructor(private val value: JsonField) : Enum { diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreateParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreateParamsTest.kt index da33364d..e1df6d79 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreateParamsTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreateParamsTest.kt @@ -18,6 +18,12 @@ internal class ResponseCreateParamsTest { fun create() { ResponseCreateParams.builder() .background(true) + .addContextManagement( + ResponseCreateParams.ContextManagement.builder() + .type("type") + .compactThreshold(1000L) + .build() + ) .conversation("string") .addInclude(ResponseIncludable.FILE_SEARCH_CALL_RESULTS) .input("string") @@ -90,6 +96,12 @@ internal class ResponseCreateParamsTest { val params = ResponseCreateParams.builder() .background(true) + .addContextManagement( + ResponseCreateParams.ContextManagement.builder() + .type("type") + .compactThreshold(1000L) + .build() + ) .conversation("string") .addInclude(ResponseIncludable.FILE_SEARCH_CALL_RESULTS) .input("string") @@ -159,6 +171,13 @@ internal class ResponseCreateParamsTest { val body = params._body() assertThat(body.background()).contains(true) + assertThat(body.contextManagement().getOrNull()) + .containsExactly( + ResponseCreateParams.ContextManagement.builder() + .type("type") + .compactThreshold(1000L) + .build() + ) assertThat(body.conversation()).contains(ResponseCreateParams.Conversation.ofId("string")) assertThat(body.include().getOrNull()) .containsExactly(ResponseIncludable.FILE_SEARCH_CALL_RESULTS) diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/ResponseServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/ResponseServiceAsyncTest.kt index 5948f688..d24c9ddf 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/async/ResponseServiceAsyncTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/ResponseServiceAsyncTest.kt @@ -36,6 +36,12 @@ internal class ResponseServiceAsyncTest { responseServiceAsync.create( ResponseCreateParams.builder() .background(true) + .addContextManagement( + ResponseCreateParams.ContextManagement.builder() + .type("type") + .compactThreshold(1000L) + .build() + ) .conversation("string") .addInclude(ResponseIncludable.FILE_SEARCH_CALL_RESULTS) .input("string") @@ -122,6 +128,12 @@ internal class ResponseServiceAsyncTest { responseServiceAsync.createStreaming( ResponseCreateParams.builder() .background(true) + .addContextManagement( + ResponseCreateParams.ContextManagement.builder() + .type("type") + .compactThreshold(1000L) + .build() + ) .conversation("string") .addInclude(ResponseIncludable.FILE_SEARCH_CALL_RESULTS) .input("string") diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/ResponseServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/ResponseServiceTest.kt index e0acab40..e6adc427 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/blocking/ResponseServiceTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/ResponseServiceTest.kt @@ -36,6 +36,12 @@ internal class ResponseServiceTest { responseService.create( ResponseCreateParams.builder() .background(true) + .addContextManagement( + ResponseCreateParams.ContextManagement.builder() + .type("type") + .compactThreshold(1000L) + .build() + ) .conversation("string") .addInclude(ResponseIncludable.FILE_SEARCH_CALL_RESULTS) .input("string") @@ -121,6 +127,12 @@ internal class ResponseServiceTest { responseService.createStreaming( ResponseCreateParams.builder() .background(true) + .addContextManagement( + ResponseCreateParams.ContextManagement.builder() + .type("type") + .compactThreshold(1000L) + .build() + ) .conversation("string") .addInclude(ResponseIncludable.FILE_SEARCH_CALL_RESULTS) .input("string") From abac4062e80b914d452c948e3dadfac059fe93f5 Mon Sep 17 00:00:00 2001 From: Alex Chang Date: Sun, 8 Feb 2026 16:09:02 -0500 Subject: [PATCH 6/7] Fix webhook merge fallout and align signature parsing --- .../services/blocking/WebhookServiceImpl.kt | 13 ++- .../services/async/WebhookServiceAsyncTest.kt | 64 ++++++++++++-- .../services/blocking/WebhookServiceTest.kt | 83 +++++++++++-------- 3 files changed, 117 insertions(+), 43 deletions(-) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/WebhookServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/WebhookServiceImpl.kt index 9eba8388..5f118bce 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/WebhookServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/WebhookServiceImpl.kt @@ -79,7 +79,7 @@ class WebhookServiceImpl internal constructor(private val clientOptions: ClientO try { timestampHeader.toLong() } catch (e: NumberFormatException) { - throw IllegalArgumentException("Invalid webhook timestamp format", e) + throw InvalidWebhookSignatureException("Invalid webhook timestamp format", e) } val now = Instant.now(clientOptions.clock) @@ -95,7 +95,11 @@ class WebhookServiceImpl internal constructor(private val clientOptions: ClientO } // The signature header can have multiple values, separated by spaces. - val signatures = signatureHeader.split(" ").map { it.removePrefix("v1,") } + val signatures = + signatureHeader + .split("\\s+".toRegex()) + .filter { it.isNotBlank() } + .map { it.removePrefix("v1,") } // Decode the secret if it starts with whsec_ val decodedSecret = @@ -119,7 +123,10 @@ class WebhookServiceImpl internal constructor(private val clientOptions: ClientO // Accept if any signature matches using timing-safe comparison val signatureMatches = signatures.any { signature -> - MessageDigest.isEqual(expectedSignature.toByteArray(), signature.toByteArray()) + MessageDigest.isEqual( + expectedSignature.toByteArray(StandardCharsets.UTF_8), + signature.toByteArray(StandardCharsets.UTF_8), + ) } if (!signatureMatches) { diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/WebhookServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/WebhookServiceAsyncTest.kt index 255b0231..f7325c5f 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/async/WebhookServiceAsyncTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/WebhookServiceAsyncTest.kt @@ -5,26 +5,78 @@ package com.openai.services.async import com.openai.TestServerExtension import com.openai.client.okhttp.OpenAIOkHttpClientAsync import com.openai.core.http.Headers +import com.openai.models.webhooks.WebhookVerificationParams +import java.time.Clock +import java.time.Instant +import java.time.ZoneOffset +import kotlin.test.assertTrue import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.extension.ExtendWith @ExtendWith(TestServerExtension::class) internal class WebhookServiceAsyncTest { + private val testPayload = + """{"id": "evt_685c059ae3a481909bdc86819b066fb6", "object": "event", "created_at": 1750861210, "type": "response.completed", "data": {"id": "resp_123"}}""" + private val testSecret = "whsec_RdvaYFYUXuIFuEbvZHwMfYFhUf7aMYjYcmM24+Aj40c=" + private val fixedTimestamp = "1750861210" + private val webhookId = "wh_685c059ae39c8190af8c71ed1022a24d" + private val validSignatureForSecret = "v1,gUAg4R2hWouRZqRQG4uJypNS8YK885G838+EHb4nKBY=" + private val fixedClock = + Clock.fixed(Instant.ofEpochSecond(fixedTimestamp.toLong()), ZoneOffset.UTC) + @Test - fun unwrap() { + fun unwrapWithValidSignatureAndSecret() { val client = OpenAIOkHttpClientAsync.builder() .baseUrl(TestServerExtension.BASE_URL) .apiKey("My API Key") + .clock(fixedClock) .build() val webhookServiceAsync = client.webhooks() - val payload = - "{\"id\":\"id\",\"created_at\":0,\"data\":{\"id\":\"id\"},\"type\":\"batch.cancelled\",\"object\":\"event\"}" - val webhookSecret = "whsec_c2VjcmV0Cg==" - val headers = Headers.builder().build() + val headers = + Headers.builder() + .put("webhook-signature", validSignatureForSecret) + .put("webhook-timestamp", fixedTimestamp) + .put("webhook-id", webhookId) + .build() + + val event = + webhookServiceAsync + .unwrap( + WebhookVerificationParams.builder() + .payload(testPayload) + .headers(headers) + .secret(testSecret) + .build() + ) + .validate() + + assertTrue(event.isResponseCompleted()) + } + + @Test + fun unwrapWithoutSecretShouldThrow() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val webhookServiceAsync = client.webhooks() + + val headers = + Headers.builder() + .put("webhook-signature", validSignatureForSecret) + .put("webhook-timestamp", fixedTimestamp) + .put("webhook-id", webhookId) + .build() - webhookServiceAsync.unwrap(payload).validate() + assertThrows { + webhookServiceAsync.unwrap( + WebhookVerificationParams.builder().payload(testPayload).headers(headers).build() + ) + } } } diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/WebhookServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/WebhookServiceTest.kt index 6938c9c3..72f41768 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/blocking/WebhookServiceTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/WebhookServiceTest.kt @@ -1,4 +1,3 @@ -<<<<<<< HEAD // File generated from our OpenAPI spec by Stainless. package com.openai.services.blocking @@ -45,6 +44,32 @@ internal class WebhookServiceTest { .build() } + @Test + fun unwrapWithValidSignatureAndSecret() { + val client = createClientWithFixedClock() + val webhookService = client.webhooks() + + val headers = + Headers.builder() + .put("webhook-signature", validSignatureForSecret) + .put("webhook-timestamp", fixedTimestamp) + .put("webhook-id", webhookId) + .build() + + val event = + webhookService + .unwrap( + WebhookVerificationParams.builder() + .payload(testPayload) + .headers(headers) + .secret(testSecret) + .build() + ) + .validate() + + assertTrue(event.isResponseCompleted()) + } + @Test fun unwrapWithoutSecretShouldThrow() { val client = @@ -124,6 +149,29 @@ internal class WebhookServiceTest { } } + @Test + fun verifySignatureWithInvalidTimestampFormat() { + val client = createClientWithFixedClock() + val webhookService = client.webhooks() + + val headers = + Headers.builder() + .put("webhook-signature", "v1,invalid_signature") + .put("webhook-timestamp", "not_a_number") + .put("webhook-id", webhookId) + .build() + + assertThrows { + webhookService.verifySignature( + WebhookVerificationParams.builder() + .payload(testPayload) + .headers(headers) + .secret(testSecret) + .build() + ) + } + } + @Test fun verifySignatureWithValidSignature() { val client = createClientWithFixedClock() @@ -227,36 +275,3 @@ internal class WebhookServiceTest { } } } -||||||| parent of 8235a47f (feat(api): add webhook signature verification) -======= -// File generated from our OpenAPI spec by Stainless. - -package com.openai.services.blocking - -import com.openai.TestServerExtension -import com.openai.client.okhttp.OpenAIOkHttpClient -import com.openai.core.http.Headers -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith - -@ExtendWith(TestServerExtension::class) -internal class WebhookServiceTest { - - @Test - fun unwrap() { - val client = - OpenAIOkHttpClient.builder() - .baseUrl(TestServerExtension.BASE_URL) - .apiKey("My API Key") - .build() - val webhookService = client.webhooks() - - val payload = - "{\"id\":\"id\",\"created_at\":0,\"data\":{\"id\":\"id\"},\"type\":\"batch.cancelled\",\"object\":\"event\"}" - val webhookSecret = "whsec_c2VjcmV0Cg==" - val headers = Headers.builder().build() - - webhookService.unwrap(payload).validate() - } -} ->>>>>>> 8235a47f (feat(api): add webhook signature verification) From 2da90dbc964aed21e5793cca37994b931a0dd636 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 05:33:18 +0000 Subject: [PATCH 7/7] release: 4.19.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 15 +++++++++++++++ README.md | 14 +++++++------- build.gradle.kts | 2 +- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 052d78b7..647ed9ca 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.18.0" + ".": "4.19.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 090330c7..78ee6002 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 4.19.0 (2026-02-09) + +Full Changelog: [v4.18.0...v4.19.0](https://github.com/openai/openai-java/compare/v4.18.0...v4.19.0) + +### Features + +* **api:** add context_management to responses ([da0fb59](https://github.com/openai/openai-java/commit/da0fb59b0e0362ee68353829c97ac8b2944cd49b)) +* **api:** add webhook signature verification ([1823eca](https://github.com/openai/openai-java/commit/1823ecab53fd72ef7f7fdc7776e6ecd631307f7c)) +* **api:** responses context_management ([c0f2cd1](https://github.com/openai/openai-java/commit/c0f2cd1c854d6fca90c9000de46f042e64a8cbf5)) + + +### Chores + +* **internal:** upgrade AssertJ ([5c01787](https://github.com/openai/openai-java/commit/5c017872b071272eff021318dab9a4a774cfcd4c)) + ## 4.18.0 (2026-02-05) Full Changelog: [v4.17.0...v4.18.0](https://github.com/openai/openai-java/compare/v4.17.0...v4.18.0) diff --git a/README.md b/README.md index be008a1e..bad6ed44 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/4.18.0) -[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/4.18.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/4.18.0) +[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/4.19.0) +[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/4.19.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/4.19.0) @@ -11,7 +11,7 @@ The OpenAI Java SDK provides convenient access to the [OpenAI REST API](https:// -The REST API documentation can be found on [platform.openai.com](https://platform.openai.com/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.openai/openai-java/4.18.0). +The REST API documentation can be found on [platform.openai.com](https://platform.openai.com/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.openai/openai-java/4.19.0). @@ -24,7 +24,7 @@ The REST API documentation can be found on [platform.openai.com](https://platfor ### Gradle ```kotlin -implementation("com.openai:openai-java:4.18.0") +implementation("com.openai:openai-java:4.19.0") ``` ### Maven @@ -33,7 +33,7 @@ implementation("com.openai:openai-java:4.18.0") com.openai openai-java - 4.18.0 + 4.19.0 ``` @@ -1342,7 +1342,7 @@ If you're using Spring Boot, then you can use the SDK's [Spring Boot starter](ht #### Gradle ```kotlin -implementation("com.openai:openai-java-spring-boot-starter:4.18.0") +implementation("com.openai:openai-java-spring-boot-starter:4.19.0") ``` #### Maven @@ -1351,7 +1351,7 @@ implementation("com.openai:openai-java-spring-boot-starter:4.18.0") com.openai openai-java-spring-boot-starter - 4.18.0 + 4.19.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index bbfa8a07..1a7dcb63 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.openai" - version = "4.18.0" // x-release-please-version + version = "4.19.0" // x-release-please-version } subprojects {