Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "4.30.0"
".": "4.31.0"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 151
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-00994178cc8e20d71754b00c54b0e4f5b4128e1c1cce765e9b7d696bd8c80d33.yml
openapi_spec_hash: 81f404053b663f987209b4fb2d08a230
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-dd99495ad509338e6de862802839360dfe394d5cd6d6ba6d13fec8fca92328b8.yml
openapi_spec_hash: 68abda9122013a9ae3f084cfdbe8e8c1
config_hash: 5635033cdc8c930255f8b529a78de722
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
# Changelog

## 4.31.0 (2026-04-04)

Full Changelog: [v4.30.0...v4.31.0](https://github.com/openai/openai-java/compare/v4.30.0...v4.31.0)

### Features

* **api:** add phase field to conversations Message ([e562a17](https://github.com/openai/openai-java/commit/e562a1701cfb7c92aa308d80d7bfe8e99c6394c8))
* **api:** add WEB_SEARCH_CALL_RESULTS to ResponseIncludable enum ([eda0a61](https://github.com/openai/openai-java/commit/eda0a61f837af3a0aba2851a23320aadfce82979))


### Bug Fixes

* **api:** remove web_search_call.results from ResponseIncludable ([936b2ab](https://github.com/openai/openai-java/commit/936b2ab08e8641bd1d6a1b2432140762185e22eb))


### Chores

* **internal:** update multipart form array serialization ([240ca42](https://github.com/openai/openai-java/commit/240ca42401366b75cf70b0eb0ff9f63425c9b358))
* **tests:** bump steady to v0.20.1 ([a3c95b0](https://github.com/openai/openai-java/commit/a3c95b073d7b10a13ce83865947ab4fbec5a95d0))
* **tests:** bump steady to v0.20.2 ([78b1d56](https://github.com/openai/openai-java/commit/78b1d5629bf7d31173ec1cec50f3191959cdba9d))


### Documentation

* **api:** clarify file_batches usage in vector stores files and file batches ([9c56841](https://github.com/openai/openai-java/commit/9c56841ff2f052a7e54290b36c3f74528be3de19))

## 4.30.0 (2026-03-25)

Full Changelog: [v4.29.1...v4.30.0](https://github.com/openai/openai-java/compare/v4.29.1...v4.30.0)
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

<!-- x-release-please-start-version -->

[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/4.30.0)
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/4.30.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/4.30.0)
[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/4.31.0)
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/4.31.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/4.31.0)

<!-- x-release-please-end -->

The OpenAI Java SDK provides convenient access to the [OpenAI REST API](https://platform.openai.com/docs) from applications written in Java.

<!-- x-release-please-start-version -->

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.30.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.31.0).

<!-- x-release-please-end -->

Expand All @@ -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.30.0")
implementation("com.openai:openai-java:4.31.0")
```

### Maven
Expand All @@ -33,7 +33,7 @@ implementation("com.openai:openai-java:4.30.0")
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>4.30.0</version>
<version>4.31.0</version>
</dependency>
```

Expand Down Expand Up @@ -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.30.0")
implementation("com.openai:openai-java-spring-boot-starter:4.31.0")
```

#### Maven
Expand All @@ -1351,7 +1351,7 @@ implementation("com.openai:openai-java-spring-boot-starter:4.30.0")
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java-spring-boot-starter</artifactId>
<version>4.30.0</version>
<version>4.31.0</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ repositories {

allprojects {
group = "com.openai"
version = "4.30.0" // x-release-please-version
version = "4.31.0" // x-release-please-version
}

subprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ private constructor(
private val role: JsonField<Role>,
private val status: JsonField<Status>,
private val type: JsonValue,
private val phase: JsonField<Phase>,
private val additionalProperties: MutableMap<String, JsonValue>,
) {

Expand All @@ -56,7 +57,8 @@ private constructor(
@JsonProperty("role") @ExcludeMissing role: JsonField<Role> = JsonMissing.of(),
@JsonProperty("status") @ExcludeMissing status: JsonField<Status> = JsonMissing.of(),
@JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(),
) : this(id, content, role, status, type, mutableMapOf())
@JsonProperty("phase") @ExcludeMissing phase: JsonField<Phase> = JsonMissing.of(),
) : this(id, content, role, status, type, phase, mutableMapOf())

/**
* The unique ID of the message.
Expand Down Expand Up @@ -105,6 +107,17 @@ private constructor(
*/
@JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type

/**
* Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer
* (`final_answer`). For models like `gpt-5.3-codex` and beyond, when sending follow-up
* requests, preserve and resend phase on all assistant messages — dropping it can degrade
* performance. Not used for user messages.
*
* @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the
* server responded with an unexpected value).
*/
fun phase(): Optional<Phase> = phase.getOptional("phase")

/**
* Returns the raw JSON value of [id].
*
Expand Down Expand Up @@ -133,6 +146,13 @@ private constructor(
*/
@JsonProperty("status") @ExcludeMissing fun _status(): JsonField<Status> = status

/**
* Returns the raw JSON value of [phase].
*
* Unlike [phase], this method doesn't throw if the JSON field has an unexpected type.
*/
@JsonProperty("phase") @ExcludeMissing fun _phase(): JsonField<Phase> = phase

@JsonAnySetter
private fun putAdditionalProperty(key: String, value: JsonValue) {
additionalProperties.put(key, value)
Expand Down Expand Up @@ -169,6 +189,7 @@ private constructor(
private var role: JsonField<Role>? = null
private var status: JsonField<Status>? = null
private var type: JsonValue = JsonValue.from("message")
private var phase: JsonField<Phase> = JsonMissing.of()
private var additionalProperties: MutableMap<String, JsonValue> = mutableMapOf()

@JvmSynthetic
Expand All @@ -178,6 +199,7 @@ private constructor(
role = message.role
status = message.status
type = message.type
phase = message.phase
additionalProperties = message.additionalProperties.toMutableMap()
}

Expand Down Expand Up @@ -359,6 +381,25 @@ private constructor(
*/
fun type(type: JsonValue) = apply { this.type = type }

/**
* Labels an `assistant` message as intermediate commentary (`commentary`) or the final
* answer (`final_answer`). For models like `gpt-5.3-codex` and beyond, when sending
* follow-up requests, preserve and resend phase on all assistant messages — dropping it can
* degrade performance. Not used for user messages.
*/
fun phase(phase: Phase?) = phase(JsonField.ofNullable(phase))

/** Alias for calling [Builder.phase] with `phase.orElse(null)`. */
fun phase(phase: Optional<Phase>) = phase(phase.getOrNull())

/**
* Sets [Builder.phase] to an arbitrary JSON value.
*
* You should usually call [Builder.phase] with a well-typed [Phase] value instead. This
* method is primarily for setting the field to an undocumented or not yet supported value.
*/
fun phase(phase: JsonField<Phase>) = apply { this.phase = phase }

fun additionalProperties(additionalProperties: Map<String, JsonValue>) = apply {
this.additionalProperties.clear()
putAllAdditionalProperties(additionalProperties)
Expand Down Expand Up @@ -400,6 +441,7 @@ private constructor(
checkRequired("role", role),
checkRequired("status", status),
type,
phase,
additionalProperties.toMutableMap(),
)
}
Expand All @@ -420,6 +462,7 @@ private constructor(
throw OpenAIInvalidDataException("'type' is invalid, received $it")
}
}
phase().ifPresent { it.validate() }
validated = true
}

Expand All @@ -442,7 +485,8 @@ private constructor(
(content.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) +
(role.asKnown().getOrNull()?.validity() ?: 0) +
(status.asKnown().getOrNull()?.validity() ?: 0) +
type.let { if (it == JsonValue.from("message")) 1 else 0 }
type.let { if (it == JsonValue.from("message")) 1 else 0 } +
(phase.asKnown().getOrNull()?.validity() ?: 0)

/** A content part that makes up an input or output item. */
@JsonDeserialize(using = Content.Deserializer::class)
Expand Down Expand Up @@ -1379,6 +1423,137 @@ private constructor(
override fun toString() = value.toString()
}

/**
* Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer
* (`final_answer`). For models like `gpt-5.3-codex` and beyond, when sending follow-up
* requests, preserve and resend phase on all assistant messages — dropping it can degrade
* performance. Not used for user messages.
*/
class Phase @JsonCreator private constructor(private val value: JsonField<String>) : Enum {

/**
* Returns this class instance's raw value.
*
* This is usually only useful if this instance was deserialized from data that doesn't
* match any known member, and you want to know that value. For example, if the SDK is on an
* older version than the API, then the API may respond with new members that the SDK is
* unaware of.
*/
@com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField<String> = value

companion object {

@JvmField val COMMENTARY = of("commentary")

@JvmField val FINAL_ANSWER = of("final_answer")

@JvmStatic fun of(value: String) = Phase(JsonField.of(value))
}

/** An enum containing [Phase]'s known values. */
enum class Known {
COMMENTARY,
FINAL_ANSWER,
}

/**
* An enum containing [Phase]'s known values, as well as an [_UNKNOWN] member.
*
* An instance of [Phase] can contain an unknown value in a couple of cases:
* - It was deserialized from data that doesn't match any known member. For example, if the
* SDK is on an older version than the API, then the API may respond with new members that
* the SDK is unaware of.
* - It was constructed with an arbitrary value using the [of] method.
*/
enum class Value {
COMMENTARY,
FINAL_ANSWER,
/** An enum member indicating that [Phase] was instantiated with an unknown value. */
_UNKNOWN,
}

/**
* Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
* if the class was instantiated with an unknown value.
*
* Use the [known] method instead if you're certain the value is always known or if you want
* to throw for the unknown case.
*/
fun value(): Value =
when (this) {
COMMENTARY -> Value.COMMENTARY
FINAL_ANSWER -> Value.FINAL_ANSWER
else -> Value._UNKNOWN
}

/**
* Returns an enum member corresponding to this class instance's value.
*
* Use the [value] method instead if you're uncertain the value is always known and don't
* want to throw for the unknown case.
*
* @throws OpenAIInvalidDataException if this class instance's value is a not a known
* member.
*/
fun known(): Known =
when (this) {
COMMENTARY -> Known.COMMENTARY
FINAL_ANSWER -> Known.FINAL_ANSWER
else -> throw OpenAIInvalidDataException("Unknown Phase: $value")
}

/**
* Returns this class instance's primitive wire representation.
*
* This differs from the [toString] method because that method is primarily for debugging
* and generally doesn't throw.
*
* @throws OpenAIInvalidDataException if this class instance's value does not have the
* expected primitive type.
*/
fun asString(): String =
_value().asString().orElseThrow { OpenAIInvalidDataException("Value is not a String") }

private var validated: Boolean = false

fun validate(): Phase = apply {
if (validated) {
return@apply
}

known()
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 (value() == Value._UNKNOWN) 0 else 1

override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}

return other is Phase && value == other.value
}

override fun hashCode() = value.hashCode()

override fun toString() = value.toString()
}

override fun equals(other: Any?): Boolean {
if (this === other) {
return true
Expand All @@ -1390,15 +1565,16 @@ private constructor(
role == other.role &&
status == other.status &&
type == other.type &&
phase == other.phase &&
additionalProperties == other.additionalProperties
}

private val hashCode: Int by lazy {
Objects.hash(id, content, role, status, type, additionalProperties)
Objects.hash(id, content, role, status, type, phase, additionalProperties)
}

override fun hashCode(): Int = hashCode

override fun toString() =
"Message{id=$id, content=$content, role=$role, status=$status, type=$type, additionalProperties=$additionalProperties}"
"Message{id=$id, content=$content, role=$role, status=$status, type=$type, phase=$phase, additionalProperties=$additionalProperties}"
}
Loading
Loading