diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6ce3d043..0ce7297f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: run: ./scripts/lint build: - timeout-minutes: 15 + timeout-minutes: 30 name: build permissions: contents: read @@ -67,23 +67,51 @@ jobs: GRADLE_OPTS: "-Dkotlin.compiler.execution.strategy=in-process" run: ./scripts/build - - name: Get GitHub OIDC Token - if: github.repository == 'stainless-sdks/openai-java' - id: github-oidc - uses: actions/github-script@v8 - with: - script: core.setOutput('github_token', await core.getIDToken()); - - name: Build and upload Maven artifacts if: github.repository == 'stainless-sdks/openai-java' env: URL: https://pkg.stainless.com/s - AUTH: ${{ steps.github-oidc.outputs.github_token }} SHA: ${{ github.sha }} PROJECT: openai-java - run: ./scripts/upload-artifacts + run: | + set -euo pipefail + + max_retries=5 + attempt=1 + + while true; do + echo "Maven artifact upload attempt ${attempt}/${max_retries}" + + oidc_response="$(curl -sSf \ + -H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ + "${ACTIONS_ID_TOKEN_REQUEST_URL}")" + github_token="$(printf '%s' "$oidc_response" | jq -er '.value')" + + upload_log="$(mktemp)" + set +e + AUTH="$github_token" ./scripts/upload-artifacts 2>&1 | tee "$upload_log" + upload_status=${PIPESTATUS[0]} + set -e + + if [ "$upload_status" -eq 0 ]; then + break + fi + + if [ "$attempt" -lt "$max_retries" ] && \ + grep -q "Failed to get valid signed URL" "$upload_log" && \ + grep -q "GitHub JWT is missing or invalid\\." "$upload_log"; then + sleep_seconds=$((3 * (1 << (attempt - 1)))) + echo "Retrying after fresh OIDC token due to transient GitHub JWT validation failure" + echo "Sleeping ${sleep_seconds}s before retry" + sleep "$sleep_seconds" + attempt=$((attempt + 1)) + continue + fi + + exit "$upload_status" + done test: - timeout-minutes: 15 + timeout-minutes: 30 name: test runs-on: ${{ github.repository == 'stainless-sdks/openai-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c032d3110..69e5aa20c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.22.0" + ".": "4.23.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index fe36e289f..704ee3211 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 147 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-a6dd5f8d7318fb1c5370d5ccb7148bacdfb3f3a665c4b85b7666e6188d9bd909.yml -openapi_spec_hash: c4824e385a81b9021428304ccc96538f -config_hash: 948733484caf41e71093c6582dbc319c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-a0aa54a302fbd7fff4ed7ad8a8547587d37b63324fc4af652bfa685ee9f8da44.yml +openapi_spec_hash: e45c5af19307cfc8b9baa4b8f8e865a0 +config_hash: 4c2841519fd72fe44c18de4c18db231f diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f0c2344d..293a40237 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,32 @@ # Changelog +## 4.23.0 (2026-02-23) + +Full Changelog: [v4.22.0...v4.23.0](https://github.com/openai/openai-java/compare/v4.22.0...v4.23.0) + +### Features + +* **api:** add gpt-realtime-1.5 and gpt-audio-1.5 models to realtime session ([b00b515](https://github.com/openai/openai-java/commit/b00b515f591c8651ab4d5d46606e31a69787eebf)) + + +### Bug Fixes + +* **api:** manual updates ([bd83804](https://github.com/openai/openai-java/commit/bd83804f76f2be62a2a09e4b9f2ed7832fdb740f)) +* set Accept header in more places ([9e2e714](https://github.com/openai/openai-java/commit/9e2e7145e357dfe6e8b3f8701df70a42e07a4f63)) +* **tests:** skip unsupported streaming tests ([24f9854](https://github.com/openai/openai-java/commit/24f9854de6299572a6b836059855218f68f2e412)) + + +### Chores + +* drop apache dependency ([37805bf](https://github.com/openai/openai-java/commit/37805bf5dad1f503cec009dfaca6c6b2b21fc279)) +* make `Properties` more resilient to `null` ([0039eb0](https://github.com/openai/openai-java/commit/0039eb008840c33d9f62d44999e4b4533a3a50d2)) + + +### Documentation + +* **api:** add batch size limit to file batch create parameters ([764fd86](https://github.com/openai/openai-java/commit/764fd868ab4d0f9642ae2facb6ca98ef3a491888)) +* **api:** clarify safety_identifier max length in chat completions and responses ([b2735b0](https://github.com/openai/openai-java/commit/b2735b002e3591513ea743062e36d6f965f1fd46)) + ## 4.22.0 (2026-02-19) Full Changelog: [v4.21.0...v4.22.0](https://github.com/openai/openai-java/compare/v4.21.0...v4.22.0) diff --git a/README.md b/README.md index 9ac179bea..49b96936b 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.22.0) -[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/4.22.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/4.22.0) +[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/4.23.0) +[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/4.23.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/4.23.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.22.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.23.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.22.0") +implementation("com.openai:openai-java:4.23.0") ``` ### Maven @@ -33,7 +33,7 @@ implementation("com.openai:openai-java:4.22.0") com.openai openai-java - 4.22.0 + 4.23.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.22.0") +implementation("com.openai:openai-java-spring-boot-starter:4.23.0") ``` #### Maven @@ -1351,7 +1351,7 @@ implementation("com.openai:openai-java-spring-boot-starter:4.22.0") com.openai openai-java-spring-boot-starter - 4.22.0 + 4.23.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index 2918ba8ac..d6eea49e8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.openai" - version = "4.22.0" // x-release-please-version + version = "4.23.0" // x-release-please-version } subprojects { diff --git a/openai-java-core/build.gradle.kts b/openai-java-core/build.gradle.kts index cddd7776f..b723288c6 100644 --- a/openai-java-core/build.gradle.kts +++ b/openai-java-core/build.gradle.kts @@ -29,8 +29,6 @@ dependencies { implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.2") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.2") - implementation("org.apache.httpcomponents.core5:httpcore5:5.2.4") - implementation("org.apache.httpcomponents.client5:httpclient5:5.3.1") implementation("com.github.victools:jsonschema-generator:4.38.0") implementation("com.github.victools:jsonschema-module-jackson:4.38.0") implementation("com.github.victools:jsonschema-module-swagger-2:4.38.0") diff --git a/openai-java-core/src/main/kotlin/com/openai/core/Properties.kt b/openai-java-core/src/main/kotlin/com/openai/core/Properties.kt index 677d5fd60..354311006 100644 --- a/openai-java-core/src/main/kotlin/com/openai/core/Properties.kt +++ b/openai-java-core/src/main/kotlin/com/openai/core/Properties.kt @@ -34,9 +34,9 @@ fun getOsName(): String { } } -fun getOsVersion(): String = System.getProperty("os.version", "unknown") +fun getOsVersion(): String = System.getProperty("os.version", "unknown") ?: "unknown" fun getPackageVersion(): String = - OpenAIClient::class.java.`package`.implementationVersion ?: "unknown" + OpenAIClient::class.java.`package`?.implementationVersion ?: "unknown" -fun getJavaVersion(): String = System.getProperty("java.version", "unknown") +fun getJavaVersion(): String = System.getProperty("java.version", "unknown") ?: "unknown" diff --git a/openai-java-core/src/main/kotlin/com/openai/core/http/HttpRequestBodies.kt b/openai-java-core/src/main/kotlin/com/openai/core/http/HttpRequestBodies.kt index 898c83474..9c1e9e901 100644 --- a/openai-java-core/src/main/kotlin/com/openai/core/http/HttpRequestBodies.kt +++ b/openai-java-core/src/main/kotlin/com/openai/core/http/HttpRequestBodies.kt @@ -8,13 +8,13 @@ import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.databind.node.JsonNodeType import com.openai.core.MultipartField +import com.openai.core.toImmutable import com.openai.errors.OpenAIInvalidDataException +import java.io.ByteArrayInputStream import java.io.InputStream import java.io.OutputStream +import java.util.UUID import kotlin.jvm.optionals.getOrNull -import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder -import org.apache.hc.core5.http.ContentType -import org.apache.hc.core5.http.HttpEntity @JvmSynthetic internal inline fun json(jsonMapper: JsonMapper, value: T): HttpRequestBody = @@ -37,70 +37,207 @@ internal fun multipartFormData( jsonMapper: JsonMapper, fields: Map>, ): HttpRequestBody = - object : HttpRequestBody { - private val entity: HttpEntity by lazy { - MultipartEntityBuilder.create() - .apply { - fields.forEach { (name, field) -> - val knownValue = field.value.asKnown().getOrNull() - val parts = - if (knownValue is InputStream) { - // Read directly from the `InputStream` instead of reading it all - // into memory due to the `jsonMapper` serialization below. - sequenceOf(name to knownValue) - } else { - val node = jsonMapper.valueToTree(field.value) - serializePart(name, node) + MultipartBody.Builder() + .apply { + fields.forEach { (name, field) -> + val knownValue = field.value.asKnown().getOrNull() + val parts = + if (knownValue is InputStream) { + // Read directly from the `InputStream` instead of reading it all + // into memory due to the `jsonMapper` serialization below. + sequenceOf(name to knownValue) + } else { + val node = jsonMapper.valueToTree(field.value) + serializePart(name, node) + } + + parts.forEach { (name, bytes) -> + val partBody = + if (bytes is ByteArrayInputStream) { + val byteArray = bytes.readBytes() + + object : HttpRequestBody { + + override fun writeTo(outputStream: OutputStream) { + outputStream.write(byteArray) + } + + override fun contentType(): String = field.contentType + + override fun contentLength(): Long = byteArray.size.toLong() + + override fun repeatable(): Boolean = true + + override fun close() {} } + } else { + object : HttpRequestBody { + + override fun writeTo(outputStream: OutputStream) { + bytes.copyTo(outputStream) + } + + override fun contentType(): String = field.contentType - parts.forEach { (name, bytes) -> - addBinaryBody( - name, - bytes, - ContentType.parseLenient(field.contentType), - field.filename().getOrNull(), - ) + override fun contentLength(): Long = -1L + + override fun repeatable(): Boolean = false + + override fun close() = bytes.close() + } } - } + + addPart( + MultipartBody.Part.create( + name, + field.filename().getOrNull(), + field.contentType, + partBody, + ) + ) } - .build() + } } + .build() + +private fun serializePart(name: String, node: JsonNode): Sequence> = + when (node.nodeType) { + JsonNodeType.MISSING, + JsonNodeType.NULL -> emptySequence() + JsonNodeType.BINARY -> sequenceOf(name to node.binaryValue().inputStream()) + JsonNodeType.STRING -> sequenceOf(name to node.textValue().byteInputStream()) + JsonNodeType.BOOLEAN -> sequenceOf(name to node.booleanValue().toString().byteInputStream()) + JsonNodeType.NUMBER -> sequenceOf(name to node.numberValue().toString().byteInputStream()) + JsonNodeType.ARRAY -> + node.elements().asSequence().flatMap { element -> serializePart("$name[]", element) } + JsonNodeType.OBJECT -> + node.fields().asSequence().flatMap { (key, value) -> + serializePart("$name[$key]", value) + } + JsonNodeType.POJO, + null -> throw OpenAIInvalidDataException("Unexpected JsonNode type: ${node.nodeType}") + } - private fun serializePart( - name: String, - node: JsonNode, - ): Sequence> = - when (node.nodeType) { - JsonNodeType.MISSING, - JsonNodeType.NULL -> emptySequence() - JsonNodeType.BINARY -> sequenceOf(name to node.binaryValue().inputStream()) - JsonNodeType.STRING -> sequenceOf(name to node.textValue().inputStream()) - JsonNodeType.BOOLEAN -> - sequenceOf(name to node.booleanValue().toString().inputStream()) - JsonNodeType.NUMBER -> - sequenceOf(name to node.numberValue().toString().inputStream()) - JsonNodeType.ARRAY -> - node.elements().asSequence().flatMap { element -> - serializePart("$name[]", element) - } - JsonNodeType.OBJECT -> - node.fields().asSequence().flatMap { (key, value) -> - serializePart("$name[$key]", value) - } - JsonNodeType.POJO, - null -> - throw OpenAIInvalidDataException("Unexpected JsonNode type: ${node.nodeType}") +private class MultipartBody +private constructor(private val boundary: String, private val parts: List) : HttpRequestBody { + private val boundaryBytes: ByteArray = boundary.toByteArray() + private val contentType = "multipart/form-data; boundary=$boundary" + + // This must remain in sync with `contentLength`. + override fun writeTo(outputStream: OutputStream) { + parts.forEach { part -> + outputStream.write(DASHDASH) + outputStream.write(boundaryBytes) + outputStream.write(CRLF) + + outputStream.write(CONTENT_DISPOSITION) + outputStream.write(part.contentDisposition.toByteArray()) + outputStream.write(CRLF) + + outputStream.write(CONTENT_TYPE) + outputStream.write(part.contentType.toByteArray()) + outputStream.write(CRLF) + + outputStream.write(CRLF) + part.body.writeTo(outputStream) + outputStream.write(CRLF) + } + + outputStream.write(DASHDASH) + outputStream.write(boundaryBytes) + outputStream.write(DASHDASH) + outputStream.write(CRLF) + } + + override fun contentType(): String = contentType + + // This must remain in sync with `writeTo`. + override fun contentLength(): Long { + var byteCount = 0L + + parts.forEach { part -> + val contentLength = part.body.contentLength() + if (contentLength == -1L) { + return -1L } - private fun String.inputStream(): InputStream = toByteArray().inputStream() + byteCount += + DASHDASH.size + + boundaryBytes.size + + CRLF.size + + CONTENT_DISPOSITION.size + + part.contentDisposition.toByteArray().size + + CRLF.size + + CONTENT_TYPE.size + + part.contentType.toByteArray().size + + CRLF.size + + CRLF.size + + contentLength + + CRLF.size + } - override fun writeTo(outputStream: OutputStream) = entity.writeTo(outputStream) + byteCount += DASHDASH.size + boundaryBytes.size + DASHDASH.size + CRLF.size + return byteCount + } - override fun contentType(): String = entity.contentType + override fun repeatable(): Boolean = parts.all { it.body.repeatable() } - override fun contentLength(): Long = entity.contentLength + override fun close() { + parts.forEach { it.body.close() } + } - override fun repeatable(): Boolean = entity.isRepeatable + class Builder { + private val boundary = UUID.randomUUID().toString() + private val parts: MutableList = mutableListOf() - override fun close() = entity.close() + fun addPart(part: Part) = apply { parts.add(part) } + + fun build() = MultipartBody(boundary, parts.toImmutable()) + } + + class Part + private constructor( + val contentDisposition: String, + val contentType: String, + val body: HttpRequestBody, + ) { + companion object { + fun create( + name: String, + filename: String?, + contentType: String, + body: HttpRequestBody, + ): Part { + val disposition = buildString { + append("form-data; name=") + appendQuotedString(name) + if (filename != null) { + append("; filename=") + appendQuotedString(filename) + } + } + return Part(disposition, contentType, body) + } + } + } + + companion object { + private val CRLF = byteArrayOf('\r'.code.toByte(), '\n'.code.toByte()) + private val DASHDASH = byteArrayOf('-'.code.toByte(), '-'.code.toByte()) + private val CONTENT_DISPOSITION = "Content-Disposition: ".toByteArray() + private val CONTENT_TYPE = "Content-Type: ".toByteArray() + + private fun StringBuilder.appendQuotedString(key: String) { + append('"') + for (ch in key) { + when (ch) { + '\n' -> append("%0A") + '\r' -> append("%0D") + '"' -> append("%22") + else -> append(ch) + } + } + append('"') + } } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/chat/completions/ChatCompletionCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/chat/completions/ChatCompletionCreateParams.kt index 4e66cb423..73fffa0bd 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/chat/completions/ChatCompletionCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/chat/completions/ChatCompletionCreateParams.kt @@ -314,9 +314,9 @@ private constructor( /** * A stable identifier used to help detect users of your application that may be violating - * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user. We - * recommend hashing their username or email address, in order to avoid sending us any - * identifying information. + * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with + * a maximum length of 64 characters. We recommend hashing their username or email address, in + * order to avoid sending us any identifying information. * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the @@ -1484,9 +1484,9 @@ private constructor( /** * A stable identifier used to help detect users of your application that may be violating - * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user. - * We recommend hashing their username or email address, in order to avoid sending us any - * identifying information. + * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, + * with a maximum length of 64 characters. We recommend hashing their username or email + * address, in order to avoid sending us any identifying information. * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). */ fun safetyIdentifier(safetyIdentifier: String) = apply { @@ -2476,9 +2476,9 @@ private constructor( /** * A stable identifier used to help detect users of your application that may be violating - * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user. - * We recommend hashing their username or email address, in order to avoid sending us any - * identifying information. + * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, + * with a maximum length of 64 characters. We recommend hashing their username or email + * address, in order to avoid sending us any identifying information. * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the @@ -3822,8 +3822,9 @@ private constructor( /** * A stable identifier used to help detect users of your application that may be * violating OpenAI's usage policies. The IDs should be a string that uniquely - * identifies each user. We recommend hashing their username or email address, in order - * to avoid sending us any identifying information. + * identifies each user, with a maximum length of 64 characters. We recommend hashing + * their username or email address, in order to avoid sending us any identifying + * information. * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). */ fun safetyIdentifier(safetyIdentifier: String) = diff --git a/openai-java-core/src/main/kotlin/com/openai/models/realtime/RealtimeSession.kt b/openai-java-core/src/main/kotlin/com/openai/models/realtime/RealtimeSession.kt index 8e8a56591..5cdfe031d 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/realtime/RealtimeSession.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/realtime/RealtimeSession.kt @@ -1865,6 +1865,8 @@ private constructor( @JvmField val GPT_REALTIME = of("gpt-realtime") + @JvmField val GPT_REALTIME_1_5 = of("gpt-realtime-1.5") + @JvmField val GPT_REALTIME_2025_08_28 = of("gpt-realtime-2025-08-28") @JvmField val GPT_4O_REALTIME_PREVIEW = of("gpt-4o-realtime-preview") @@ -1890,6 +1892,8 @@ private constructor( @JvmField val GPT_REALTIME_MINI_2025_12_15 = of("gpt-realtime-mini-2025-12-15") + @JvmField val GPT_AUDIO_1_5 = of("gpt-audio-1.5") + @JvmField val GPT_AUDIO_MINI = of("gpt-audio-mini") @JvmField val GPT_AUDIO_MINI_2025_10_06 = of("gpt-audio-mini-2025-10-06") @@ -1902,6 +1906,7 @@ private constructor( /** An enum containing [Model]'s known values. */ enum class Known { GPT_REALTIME, + GPT_REALTIME_1_5, GPT_REALTIME_2025_08_28, GPT_4O_REALTIME_PREVIEW, GPT_4O_REALTIME_PREVIEW_2024_10_01, @@ -1912,6 +1917,7 @@ private constructor( GPT_REALTIME_MINI, GPT_REALTIME_MINI_2025_10_06, GPT_REALTIME_MINI_2025_12_15, + GPT_AUDIO_1_5, GPT_AUDIO_MINI, GPT_AUDIO_MINI_2025_10_06, GPT_AUDIO_MINI_2025_12_15, @@ -1928,6 +1934,7 @@ private constructor( */ enum class Value { GPT_REALTIME, + GPT_REALTIME_1_5, GPT_REALTIME_2025_08_28, GPT_4O_REALTIME_PREVIEW, GPT_4O_REALTIME_PREVIEW_2024_10_01, @@ -1938,6 +1945,7 @@ private constructor( GPT_REALTIME_MINI, GPT_REALTIME_MINI_2025_10_06, GPT_REALTIME_MINI_2025_12_15, + GPT_AUDIO_1_5, GPT_AUDIO_MINI, GPT_AUDIO_MINI_2025_10_06, GPT_AUDIO_MINI_2025_12_15, @@ -1955,6 +1963,7 @@ private constructor( fun value(): Value = when (this) { GPT_REALTIME -> Value.GPT_REALTIME + GPT_REALTIME_1_5 -> Value.GPT_REALTIME_1_5 GPT_REALTIME_2025_08_28 -> Value.GPT_REALTIME_2025_08_28 GPT_4O_REALTIME_PREVIEW -> Value.GPT_4O_REALTIME_PREVIEW GPT_4O_REALTIME_PREVIEW_2024_10_01 -> Value.GPT_4O_REALTIME_PREVIEW_2024_10_01 @@ -1966,6 +1975,7 @@ private constructor( GPT_REALTIME_MINI -> Value.GPT_REALTIME_MINI GPT_REALTIME_MINI_2025_10_06 -> Value.GPT_REALTIME_MINI_2025_10_06 GPT_REALTIME_MINI_2025_12_15 -> Value.GPT_REALTIME_MINI_2025_12_15 + GPT_AUDIO_1_5 -> Value.GPT_AUDIO_1_5 GPT_AUDIO_MINI -> Value.GPT_AUDIO_MINI GPT_AUDIO_MINI_2025_10_06 -> Value.GPT_AUDIO_MINI_2025_10_06 GPT_AUDIO_MINI_2025_12_15 -> Value.GPT_AUDIO_MINI_2025_12_15 @@ -1984,6 +1994,7 @@ private constructor( fun known(): Known = when (this) { GPT_REALTIME -> Known.GPT_REALTIME + GPT_REALTIME_1_5 -> Known.GPT_REALTIME_1_5 GPT_REALTIME_2025_08_28 -> Known.GPT_REALTIME_2025_08_28 GPT_4O_REALTIME_PREVIEW -> Known.GPT_4O_REALTIME_PREVIEW GPT_4O_REALTIME_PREVIEW_2024_10_01 -> Known.GPT_4O_REALTIME_PREVIEW_2024_10_01 @@ -1995,6 +2006,7 @@ private constructor( GPT_REALTIME_MINI -> Known.GPT_REALTIME_MINI GPT_REALTIME_MINI_2025_10_06 -> Known.GPT_REALTIME_MINI_2025_10_06 GPT_REALTIME_MINI_2025_12_15 -> Known.GPT_REALTIME_MINI_2025_12_15 + GPT_AUDIO_1_5 -> Known.GPT_AUDIO_1_5 GPT_AUDIO_MINI -> Known.GPT_AUDIO_MINI GPT_AUDIO_MINI_2025_10_06 -> Known.GPT_AUDIO_MINI_2025_10_06 GPT_AUDIO_MINI_2025_12_15 -> Known.GPT_AUDIO_MINI_2025_12_15 diff --git a/openai-java-core/src/main/kotlin/com/openai/models/realtime/RealtimeSessionCreateRequest.kt b/openai-java-core/src/main/kotlin/com/openai/models/realtime/RealtimeSessionCreateRequest.kt index 7463b3edb..9bad2ba3f 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/realtime/RealtimeSessionCreateRequest.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/realtime/RealtimeSessionCreateRequest.kt @@ -1137,6 +1137,8 @@ private constructor( @JvmField val GPT_REALTIME = of("gpt-realtime") + @JvmField val GPT_REALTIME_1_5 = of("gpt-realtime-1.5") + @JvmField val GPT_REALTIME_2025_08_28 = of("gpt-realtime-2025-08-28") @JvmField val GPT_4O_REALTIME_PREVIEW = of("gpt-4o-realtime-preview") @@ -1162,6 +1164,8 @@ private constructor( @JvmField val GPT_REALTIME_MINI_2025_12_15 = of("gpt-realtime-mini-2025-12-15") + @JvmField val GPT_AUDIO_1_5 = of("gpt-audio-1.5") + @JvmField val GPT_AUDIO_MINI = of("gpt-audio-mini") @JvmField val GPT_AUDIO_MINI_2025_10_06 = of("gpt-audio-mini-2025-10-06") @@ -1174,6 +1178,7 @@ private constructor( /** An enum containing [Model]'s known values. */ enum class Known { GPT_REALTIME, + GPT_REALTIME_1_5, GPT_REALTIME_2025_08_28, GPT_4O_REALTIME_PREVIEW, GPT_4O_REALTIME_PREVIEW_2024_10_01, @@ -1184,6 +1189,7 @@ private constructor( GPT_REALTIME_MINI, GPT_REALTIME_MINI_2025_10_06, GPT_REALTIME_MINI_2025_12_15, + GPT_AUDIO_1_5, GPT_AUDIO_MINI, GPT_AUDIO_MINI_2025_10_06, GPT_AUDIO_MINI_2025_12_15, @@ -1200,6 +1206,7 @@ private constructor( */ enum class Value { GPT_REALTIME, + GPT_REALTIME_1_5, GPT_REALTIME_2025_08_28, GPT_4O_REALTIME_PREVIEW, GPT_4O_REALTIME_PREVIEW_2024_10_01, @@ -1210,6 +1217,7 @@ private constructor( GPT_REALTIME_MINI, GPT_REALTIME_MINI_2025_10_06, GPT_REALTIME_MINI_2025_12_15, + GPT_AUDIO_1_5, GPT_AUDIO_MINI, GPT_AUDIO_MINI_2025_10_06, GPT_AUDIO_MINI_2025_12_15, @@ -1227,6 +1235,7 @@ private constructor( fun value(): Value = when (this) { GPT_REALTIME -> Value.GPT_REALTIME + GPT_REALTIME_1_5 -> Value.GPT_REALTIME_1_5 GPT_REALTIME_2025_08_28 -> Value.GPT_REALTIME_2025_08_28 GPT_4O_REALTIME_PREVIEW -> Value.GPT_4O_REALTIME_PREVIEW GPT_4O_REALTIME_PREVIEW_2024_10_01 -> Value.GPT_4O_REALTIME_PREVIEW_2024_10_01 @@ -1238,6 +1247,7 @@ private constructor( GPT_REALTIME_MINI -> Value.GPT_REALTIME_MINI GPT_REALTIME_MINI_2025_10_06 -> Value.GPT_REALTIME_MINI_2025_10_06 GPT_REALTIME_MINI_2025_12_15 -> Value.GPT_REALTIME_MINI_2025_12_15 + GPT_AUDIO_1_5 -> Value.GPT_AUDIO_1_5 GPT_AUDIO_MINI -> Value.GPT_AUDIO_MINI GPT_AUDIO_MINI_2025_10_06 -> Value.GPT_AUDIO_MINI_2025_10_06 GPT_AUDIO_MINI_2025_12_15 -> Value.GPT_AUDIO_MINI_2025_12_15 @@ -1256,6 +1266,7 @@ private constructor( fun known(): Known = when (this) { GPT_REALTIME -> Known.GPT_REALTIME + GPT_REALTIME_1_5 -> Known.GPT_REALTIME_1_5 GPT_REALTIME_2025_08_28 -> Known.GPT_REALTIME_2025_08_28 GPT_4O_REALTIME_PREVIEW -> Known.GPT_4O_REALTIME_PREVIEW GPT_4O_REALTIME_PREVIEW_2024_10_01 -> Known.GPT_4O_REALTIME_PREVIEW_2024_10_01 @@ -1267,6 +1278,7 @@ private constructor( GPT_REALTIME_MINI -> Known.GPT_REALTIME_MINI GPT_REALTIME_MINI_2025_10_06 -> Known.GPT_REALTIME_MINI_2025_10_06 GPT_REALTIME_MINI_2025_12_15 -> Known.GPT_REALTIME_MINI_2025_12_15 + GPT_AUDIO_1_5 -> Known.GPT_AUDIO_1_5 GPT_AUDIO_MINI -> Known.GPT_AUDIO_MINI GPT_AUDIO_MINI_2025_10_06 -> Known.GPT_AUDIO_MINI_2025_10_06 GPT_AUDIO_MINI_2025_12_15 -> Known.GPT_AUDIO_MINI_2025_12_15 diff --git a/openai-java-core/src/main/kotlin/com/openai/models/realtime/clientsecrets/RealtimeSessionCreateResponse.kt b/openai-java-core/src/main/kotlin/com/openai/models/realtime/clientsecrets/RealtimeSessionCreateResponse.kt index 7df571215..958dcb920 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/realtime/clientsecrets/RealtimeSessionCreateResponse.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/realtime/clientsecrets/RealtimeSessionCreateResponse.kt @@ -3548,6 +3548,8 @@ private constructor( @JvmField val GPT_REALTIME = of("gpt-realtime") + @JvmField val GPT_REALTIME_1_5 = of("gpt-realtime-1.5") + @JvmField val GPT_REALTIME_2025_08_28 = of("gpt-realtime-2025-08-28") @JvmField val GPT_4O_REALTIME_PREVIEW = of("gpt-4o-realtime-preview") @@ -3573,6 +3575,8 @@ private constructor( @JvmField val GPT_REALTIME_MINI_2025_12_15 = of("gpt-realtime-mini-2025-12-15") + @JvmField val GPT_AUDIO_1_5 = of("gpt-audio-1.5") + @JvmField val GPT_AUDIO_MINI = of("gpt-audio-mini") @JvmField val GPT_AUDIO_MINI_2025_10_06 = of("gpt-audio-mini-2025-10-06") @@ -3585,6 +3589,7 @@ private constructor( /** An enum containing [Model]'s known values. */ enum class Known { GPT_REALTIME, + GPT_REALTIME_1_5, GPT_REALTIME_2025_08_28, GPT_4O_REALTIME_PREVIEW, GPT_4O_REALTIME_PREVIEW_2024_10_01, @@ -3595,6 +3600,7 @@ private constructor( GPT_REALTIME_MINI, GPT_REALTIME_MINI_2025_10_06, GPT_REALTIME_MINI_2025_12_15, + GPT_AUDIO_1_5, GPT_AUDIO_MINI, GPT_AUDIO_MINI_2025_10_06, GPT_AUDIO_MINI_2025_12_15, @@ -3611,6 +3617,7 @@ private constructor( */ enum class Value { GPT_REALTIME, + GPT_REALTIME_1_5, GPT_REALTIME_2025_08_28, GPT_4O_REALTIME_PREVIEW, GPT_4O_REALTIME_PREVIEW_2024_10_01, @@ -3621,6 +3628,7 @@ private constructor( GPT_REALTIME_MINI, GPT_REALTIME_MINI_2025_10_06, GPT_REALTIME_MINI_2025_12_15, + GPT_AUDIO_1_5, GPT_AUDIO_MINI, GPT_AUDIO_MINI_2025_10_06, GPT_AUDIO_MINI_2025_12_15, @@ -3638,6 +3646,7 @@ private constructor( fun value(): Value = when (this) { GPT_REALTIME -> Value.GPT_REALTIME + GPT_REALTIME_1_5 -> Value.GPT_REALTIME_1_5 GPT_REALTIME_2025_08_28 -> Value.GPT_REALTIME_2025_08_28 GPT_4O_REALTIME_PREVIEW -> Value.GPT_4O_REALTIME_PREVIEW GPT_4O_REALTIME_PREVIEW_2024_10_01 -> Value.GPT_4O_REALTIME_PREVIEW_2024_10_01 @@ -3649,6 +3658,7 @@ private constructor( GPT_REALTIME_MINI -> Value.GPT_REALTIME_MINI GPT_REALTIME_MINI_2025_10_06 -> Value.GPT_REALTIME_MINI_2025_10_06 GPT_REALTIME_MINI_2025_12_15 -> Value.GPT_REALTIME_MINI_2025_12_15 + GPT_AUDIO_1_5 -> Value.GPT_AUDIO_1_5 GPT_AUDIO_MINI -> Value.GPT_AUDIO_MINI GPT_AUDIO_MINI_2025_10_06 -> Value.GPT_AUDIO_MINI_2025_10_06 GPT_AUDIO_MINI_2025_12_15 -> Value.GPT_AUDIO_MINI_2025_12_15 @@ -3667,6 +3677,7 @@ private constructor( fun known(): Known = when (this) { GPT_REALTIME -> Known.GPT_REALTIME + GPT_REALTIME_1_5 -> Known.GPT_REALTIME_1_5 GPT_REALTIME_2025_08_28 -> Known.GPT_REALTIME_2025_08_28 GPT_4O_REALTIME_PREVIEW -> Known.GPT_4O_REALTIME_PREVIEW GPT_4O_REALTIME_PREVIEW_2024_10_01 -> Known.GPT_4O_REALTIME_PREVIEW_2024_10_01 @@ -3678,6 +3689,7 @@ private constructor( GPT_REALTIME_MINI -> Known.GPT_REALTIME_MINI GPT_REALTIME_MINI_2025_10_06 -> Known.GPT_REALTIME_MINI_2025_10_06 GPT_REALTIME_MINI_2025_12_15 -> Known.GPT_REALTIME_MINI_2025_12_15 + GPT_AUDIO_1_5 -> Known.GPT_AUDIO_1_5 GPT_AUDIO_MINI -> Known.GPT_AUDIO_MINI GPT_AUDIO_MINI_2025_10_06 -> Known.GPT_AUDIO_MINI_2025_10_06 GPT_AUDIO_MINI_2025_12_15 -> Known.GPT_AUDIO_MINI_2025_12_15 diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/Response.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/Response.kt index c2f6a1bfc..0eff08c49 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/responses/Response.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/Response.kt @@ -443,9 +443,9 @@ private constructor( /** * A stable identifier used to help detect users of your application that may be violating - * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user. We - * recommend hashing their username or email address, in order to avoid sending us any - * identifying information. + * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with + * a maximum length of 64 characters. We recommend hashing their username or email address, in + * order to avoid sending us any identifying information. * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the @@ -1671,9 +1671,9 @@ private constructor( /** * A stable identifier used to help detect users of your application that may be violating - * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user. - * We recommend hashing their username or email address, in order to avoid sending us any - * identifying information. + * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, + * with a maximum length of 64 characters. We recommend hashing their username or email + * address, in order to avoid sending us any identifying information. * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). */ fun safetyIdentifier(safetyIdentifier: String) = 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 c08c22777..45eaef04b 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 @@ -236,9 +236,9 @@ private constructor( /** * A stable identifier used to help detect users of your application that may be violating - * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user. We - * recommend hashing their username or email address, in order to avoid sending us any - * identifying information. + * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with + * a maximum length of 64 characters. We recommend hashing their username or email address, in + * order to avoid sending us any identifying information. * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the @@ -1048,9 +1048,9 @@ private constructor( /** * A stable identifier used to help detect users of your application that may be violating - * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user. - * We recommend hashing their username or email address, in order to avoid sending us any - * identifying information. + * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, + * with a maximum length of 64 characters. We recommend hashing their username or email + * address, in order to avoid sending us any identifying information. * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). */ fun safetyIdentifier(safetyIdentifier: String) = apply { @@ -1964,9 +1964,9 @@ private constructor( /** * A stable identifier used to help detect users of your application that may be violating - * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user. - * We recommend hashing their username or email address, in order to avoid sending us any - * identifying information. + * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, + * with a maximum length of 64 characters. We recommend hashing their username or email + * address, in order to avoid sending us any identifying information. * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the @@ -2881,8 +2881,9 @@ private constructor( /** * A stable identifier used to help detect users of your application that may be * violating OpenAI's usage policies. The IDs should be a string that uniquely - * identifies each user. We recommend hashing their username or email address, in order - * to avoid sending us any identifying information. + * identifies each user, with a maximum length of 64 characters. We recommend hashing + * their username or email address, in order to avoid sending us any identifying + * information. * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). */ fun safetyIdentifier(safetyIdentifier: String) = diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponsesClientEvent.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponsesClientEvent.kt new file mode 100644 index 000000000..4a8eedc5a --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponsesClientEvent.kt @@ -0,0 +1,3693 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.responses + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer +import com.openai.core.Enum +import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.allMaxBy +import com.openai.core.checkKnown +import com.openai.core.checkRequired +import com.openai.core.getOrThrow +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import com.openai.models.ChatModel +import com.openai.models.Reasoning +import com.openai.models.ResponsesModel +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class ResponsesClientEvent +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val type: JsonValue, + private val background: JsonField, + private val contextManagement: JsonField>, + private val conversation: JsonField, + private val include: JsonField>, + private val input: JsonField, + private val instructions: JsonField, + private val maxOutputTokens: JsonField, + private val maxToolCalls: JsonField, + private val metadata: JsonField, + private val model: JsonField, + private val parallelToolCalls: JsonField, + private val previousResponseId: JsonField, + private val prompt: JsonField, + private val promptCacheKey: JsonField, + private val promptCacheRetention: JsonField, + private val reasoning: JsonField, + private val safetyIdentifier: JsonField, + private val serviceTier: JsonField, + private val store: JsonField, + private val stream: JsonField, + private val streamOptions: JsonField, + private val temperature: JsonField, + private val text: JsonField, + private val toolChoice: JsonField, + private val tools: JsonField>, + private val topLogprobs: JsonField, + private val topP: JsonField, + private val truncation: JsonField, + private val user: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("background") + @ExcludeMissing + background: JsonField = JsonMissing.of(), + @JsonProperty("context_management") + @ExcludeMissing + contextManagement: JsonField> = JsonMissing.of(), + @JsonProperty("conversation") + @ExcludeMissing + conversation: JsonField = JsonMissing.of(), + @JsonProperty("include") + @ExcludeMissing + include: JsonField> = JsonMissing.of(), + @JsonProperty("input") @ExcludeMissing input: JsonField = JsonMissing.of(), + @JsonProperty("instructions") + @ExcludeMissing + instructions: JsonField = JsonMissing.of(), + @JsonProperty("max_output_tokens") + @ExcludeMissing + maxOutputTokens: JsonField = JsonMissing.of(), + @JsonProperty("max_tool_calls") + @ExcludeMissing + maxToolCalls: JsonField = JsonMissing.of(), + @JsonProperty("metadata") @ExcludeMissing metadata: JsonField = JsonMissing.of(), + @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), + @JsonProperty("parallel_tool_calls") + @ExcludeMissing + parallelToolCalls: JsonField = JsonMissing.of(), + @JsonProperty("previous_response_id") + @ExcludeMissing + previousResponseId: JsonField = JsonMissing.of(), + @JsonProperty("prompt") + @ExcludeMissing + prompt: JsonField = JsonMissing.of(), + @JsonProperty("prompt_cache_key") + @ExcludeMissing + promptCacheKey: JsonField = JsonMissing.of(), + @JsonProperty("prompt_cache_retention") + @ExcludeMissing + promptCacheRetention: JsonField = JsonMissing.of(), + @JsonProperty("reasoning") + @ExcludeMissing + reasoning: JsonField = JsonMissing.of(), + @JsonProperty("safety_identifier") + @ExcludeMissing + safetyIdentifier: JsonField = JsonMissing.of(), + @JsonProperty("service_tier") + @ExcludeMissing + serviceTier: JsonField = JsonMissing.of(), + @JsonProperty("store") @ExcludeMissing store: JsonField = JsonMissing.of(), + @JsonProperty("stream") @ExcludeMissing stream: JsonField = JsonMissing.of(), + @JsonProperty("stream_options") + @ExcludeMissing + streamOptions: JsonField = JsonMissing.of(), + @JsonProperty("temperature") + @ExcludeMissing + temperature: JsonField = JsonMissing.of(), + @JsonProperty("text") + @ExcludeMissing + text: JsonField = JsonMissing.of(), + @JsonProperty("tool_choice") + @ExcludeMissing + toolChoice: JsonField = JsonMissing.of(), + @JsonProperty("tools") @ExcludeMissing tools: JsonField> = JsonMissing.of(), + @JsonProperty("top_logprobs") + @ExcludeMissing + topLogprobs: JsonField = JsonMissing.of(), + @JsonProperty("top_p") @ExcludeMissing topP: JsonField = JsonMissing.of(), + @JsonProperty("truncation") + @ExcludeMissing + truncation: JsonField = JsonMissing.of(), + @JsonProperty("user") @ExcludeMissing user: JsonField = JsonMissing.of(), + ) : this( + type, + background, + contextManagement, + conversation, + include, + input, + instructions, + maxOutputTokens, + maxToolCalls, + metadata, + model, + parallelToolCalls, + previousResponseId, + prompt, + promptCacheKey, + promptCacheRetention, + reasoning, + safetyIdentifier, + serviceTier, + store, + stream, + streamOptions, + temperature, + text, + toolChoice, + tools, + topLogprobs, + topP, + truncation, + user, + mutableMapOf(), + ) + + /** + * The type of the client event. Always `response.create`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("response.create") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * Whether to run the model response in the background. + * [Learn more](https://platform.openai.com/docs/guides/background). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + 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 this response are + * automatically added to this conversation after this response completes. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun conversation(): Optional = conversation.getOptional("conversation") + + /** + * Specify additional output data to include in the model response. Currently supported values + * are: + * - `web_search_call.action.sources`: Include the sources of the web search tool call. + * - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code + * interpreter tool call items. + * - `computer_call_output.output.image_url`: Include image urls from the computer call output. + * - `file_search_call.results`: Include the search results of the file search tool call. + * - `message.input_image.image_url`: Include image urls from the input message. + * - `message.output_text.logprobs`: Include logprobs with assistant messages. + * - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in + * reasoning item outputs. This enables reasoning items to be used in multi-turn conversations + * when using the Responses API statelessly (like when the `store` parameter is set to + * `false`, or when an organization is enrolled in the zero data retention program). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun include(): Optional> = include.getOptional("include") + + /** + * Text, image, or file inputs to the model, used to generate a response. + * + * Learn more: + * - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) + * - [Image inputs](https://platform.openai.com/docs/guides/images) + * - [File inputs](https://platform.openai.com/docs/guides/pdf-files) + * - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) + * - [Function calling](https://platform.openai.com/docs/guides/function-calling) + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun input(): Optional = input.getOptional("input") + + /** + * A system (or developer) message inserted into the model's context. + * + * When using along with `previous_response_id`, the instructions from a previous response will + * not be carried over to the next response. This makes it simple to swap out system (or + * developer) messages in new responses. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun instructions(): Optional = instructions.getOptional("instructions") + + /** + * An upper bound for the number of tokens that can be generated for a response, including + * visible output tokens and + * [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun maxOutputTokens(): Optional = maxOutputTokens.getOptional("max_output_tokens") + + /** + * The maximum number of total calls to built-in tools that can be processed in a response. This + * maximum number applies across all built-in tool calls, not per individual tool. Any further + * attempts to call a tool by the model will be ignored. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun maxToolCalls(): Optional = maxToolCalls.getOptional("max_tool_calls") + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format, and querying for objects via + * API or the dashboard. + * + * Keys are strings with a maximum length of 64 characters. Values are strings with a maximum + * length of 512 characters. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun metadata(): Optional = metadata.getOptional("metadata") + + /** + * Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of + * models with different capabilities, performance characteristics, and price points. Refer to + * the [model guide](https://platform.openai.com/docs/models) to browse and compare available + * models. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun model(): Optional = model.getOptional("model") + + /** + * Whether to allow the model to run tool calls in parallel. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun parallelToolCalls(): Optional = + parallelToolCalls.getOptional("parallel_tool_calls") + + /** + * The unique ID of the previous response to the model. Use this to create multi-turn + * conversations. Learn more about + * [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot be + * used in conjunction with `conversation`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun previousResponseId(): Optional = + previousResponseId.getOptional("previous_response_id") + + /** + * Reference to a prompt template and its variables. + * [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun prompt(): Optional = prompt.getOptional("prompt") + + /** + * Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. + * Replaces the `user` field. + * [Learn more](https://platform.openai.com/docs/guides/prompt-caching). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun promptCacheKey(): Optional = promptCacheKey.getOptional("prompt_cache_key") + + /** + * The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, + * which keeps cached prefixes active for longer, up to a maximum of 24 hours. + * [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun promptCacheRetention(): Optional = + promptCacheRetention.getOptional("prompt_cache_retention") + + /** + * **gpt-5 and o-series models only** + * + * Configuration options for + * [reasoning models](https://platform.openai.com/docs/guides/reasoning). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun reasoning(): Optional = reasoning.getOptional("reasoning") + + /** + * A stable identifier used to help detect users of your application that may be violating + * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, with + * a maximum length of 64 characters. We recommend hashing their username or email address, in + * order to avoid sending us any identifying information. + * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun safetyIdentifier(): Optional = safetyIdentifier.getOptional("safety_identifier") + + /** + * Specifies the processing type used for serving the request. + * - If set to 'auto', then the request will be processed with the service tier configured in + * the Project settings. Unless otherwise configured, the Project will use 'default'. + * - If set to 'default', then the request will be processed with the standard pricing and + * performance for the selected model. + * - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or + * '[priority](https://openai.com/api-priority-processing/)', then the request will be + * processed with the corresponding service tier. + * - When not set, the default behavior is 'auto'. + * + * When the `service_tier` parameter is set, the response body will include the `service_tier` + * value based on the processing mode actually used to serve the request. This response value + * may be different from the value set in the parameter. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun serviceTier(): Optional = serviceTier.getOptional("service_tier") + + /** + * Whether to store the generated model response for later retrieval via API. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun store(): Optional = store.getOptional("store") + + /** + * If set to true, the model response data will be streamed to the client as it is generated + * using + * [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). + * See the + * [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) + * for more information. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun stream(): Optional = stream.getOptional("stream") + + /** + * Options for streaming responses. Only set this when you set `stream: true`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun streamOptions(): Optional = streamOptions.getOptional("stream_options") + + /** + * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the + * output more random, while lower values like 0.2 will make it more focused and deterministic. + * We generally recommend altering this or `top_p` but not both. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun temperature(): Optional = temperature.getOptional("temperature") + + /** + * Configuration options for a text response from the model. Can be plain text or structured + * JSON data. Learn more: + * - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) + * - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun text(): Optional = text.getOptional("text") + + /** + * How the model should select which tool (or tools) to use when generating a response. See the + * `tools` parameter to see how to specify which tools the model can call. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun toolChoice(): Optional = toolChoice.getOptional("tool_choice") + + /** + * An array of tools the model may call while generating a response. You can specify which tool + * to use by setting the `tool_choice` parameter. + * + * We support the following categories of tools: + * - **Built-in tools**: Tools that are provided by OpenAI that extend the model's capabilities, + * like [web search](https://platform.openai.com/docs/guides/tools-web-search) or + * [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more about + * [built-in tools](https://platform.openai.com/docs/guides/tools). + * - **MCP Tools**: Integrations with third-party systems via custom MCP servers or predefined + * connectors such as Google Drive and SharePoint. Learn more about + * [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). + * - **Function calls (custom tools)**: Functions that are defined by you, enabling the model to + * call your own code with strongly typed arguments and outputs. Learn more about + * [function calling](https://platform.openai.com/docs/guides/function-calling). You can also + * use custom tools to call your own code. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun tools(): Optional> = tools.getOptional("tools") + + /** + * An integer between 0 and 20 specifying the number of most likely tokens to return at each + * token position, each with an associated log probability. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun topLogprobs(): Optional = topLogprobs.getOptional("top_logprobs") + + /** + * An alternative to sampling with temperature, called nucleus sampling, where the model + * considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens + * comprising the top 10% probability mass are considered. + * + * We generally recommend altering this or `temperature` but not both. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun topP(): Optional = topP.getOptional("top_p") + + /** + * The truncation strategy to use for the model response. + * - `auto`: If the input to this Response exceeds the model's context window size, the model + * will truncate the response to fit the context window by dropping items from the beginning + * of the conversation. + * - `disabled` (default): If the input size will exceed the context window size for a model, + * the request will fail with a 400 error. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun truncation(): Optional = truncation.getOptional("truncation") + + /** + * This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use + * `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for your + * end-users. Used to boost cache hit rates by better bucketing similar requests and to help + * OpenAI detect and prevent abuse. + * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + @Deprecated("deprecated") fun user(): Optional = user.getOptional("user") + + /** + * Returns the raw JSON value of [background]. + * + * Unlike [background], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("background") @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]. + * + * Unlike [conversation], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("conversation") + @ExcludeMissing + fun _conversation(): JsonField = conversation + + /** + * Returns the raw JSON value of [include]. + * + * Unlike [include], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("include") + @ExcludeMissing + fun _include(): JsonField> = include + + /** + * Returns the raw JSON value of [input]. + * + * Unlike [input], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("input") @ExcludeMissing fun _input(): JsonField = input + + /** + * Returns the raw JSON value of [instructions]. + * + * Unlike [instructions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("instructions") + @ExcludeMissing + fun _instructions(): JsonField = instructions + + /** + * Returns the raw JSON value of [maxOutputTokens]. + * + * Unlike [maxOutputTokens], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("max_output_tokens") + @ExcludeMissing + fun _maxOutputTokens(): JsonField = maxOutputTokens + + /** + * Returns the raw JSON value of [maxToolCalls]. + * + * Unlike [maxToolCalls], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("max_tool_calls") + @ExcludeMissing + fun _maxToolCalls(): JsonField = maxToolCalls + + /** + * Returns the raw JSON value of [metadata]. + * + * Unlike [metadata], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonField = metadata + + /** + * Returns the raw JSON value of [model]. + * + * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** + * Returns the raw JSON value of [parallelToolCalls]. + * + * Unlike [parallelToolCalls], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("parallel_tool_calls") + @ExcludeMissing + fun _parallelToolCalls(): JsonField = parallelToolCalls + + /** + * Returns the raw JSON value of [previousResponseId]. + * + * Unlike [previousResponseId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("previous_response_id") + @ExcludeMissing + fun _previousResponseId(): JsonField = previousResponseId + + /** + * Returns the raw JSON value of [prompt]. + * + * Unlike [prompt], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("prompt") @ExcludeMissing fun _prompt(): JsonField = prompt + + /** + * Returns the raw JSON value of [promptCacheKey]. + * + * Unlike [promptCacheKey], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("prompt_cache_key") + @ExcludeMissing + fun _promptCacheKey(): JsonField = promptCacheKey + + /** + * Returns the raw JSON value of [promptCacheRetention]. + * + * Unlike [promptCacheRetention], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("prompt_cache_retention") + @ExcludeMissing + fun _promptCacheRetention(): JsonField = promptCacheRetention + + /** + * Returns the raw JSON value of [reasoning]. + * + * Unlike [reasoning], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reasoning") @ExcludeMissing fun _reasoning(): JsonField = reasoning + + /** + * Returns the raw JSON value of [safetyIdentifier]. + * + * Unlike [safetyIdentifier], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("safety_identifier") + @ExcludeMissing + fun _safetyIdentifier(): JsonField = safetyIdentifier + + /** + * Returns the raw JSON value of [serviceTier]. + * + * Unlike [serviceTier], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("service_tier") + @ExcludeMissing + fun _serviceTier(): JsonField = serviceTier + + /** + * Returns the raw JSON value of [store]. + * + * Unlike [store], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("store") @ExcludeMissing fun _store(): JsonField = store + + /** + * Returns the raw JSON value of [stream]. + * + * Unlike [stream], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("stream") @ExcludeMissing fun _stream(): JsonField = stream + + /** + * Returns the raw JSON value of [streamOptions]. + * + * Unlike [streamOptions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("stream_options") + @ExcludeMissing + fun _streamOptions(): JsonField = streamOptions + + /** + * Returns the raw JSON value of [temperature]. + * + * Unlike [temperature], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("temperature") @ExcludeMissing fun _temperature(): JsonField = temperature + + /** + * Returns the raw JSON value of [text]. + * + * Unlike [text], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("text") @ExcludeMissing fun _text(): JsonField = text + + /** + * Returns the raw JSON value of [toolChoice]. + * + * Unlike [toolChoice], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tool_choice") + @ExcludeMissing + fun _toolChoice(): JsonField = toolChoice + + /** + * Returns the raw JSON value of [tools]. + * + * Unlike [tools], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools + + /** + * Returns the raw JSON value of [topLogprobs]. + * + * Unlike [topLogprobs], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("top_logprobs") @ExcludeMissing fun _topLogprobs(): JsonField = topLogprobs + + /** + * Returns the raw JSON value of [topP]. + * + * Unlike [topP], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("top_p") @ExcludeMissing fun _topP(): JsonField = topP + + /** + * Returns the raw JSON value of [truncation]. + * + * Unlike [truncation], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("truncation") + @ExcludeMissing + fun _truncation(): JsonField = truncation + + /** + * Returns the raw JSON value of [user]. + * + * Unlike [user], this method doesn't throw if the JSON field has an unexpected type. + */ + @Deprecated("deprecated") + @JsonProperty("user") + @ExcludeMissing + fun _user(): JsonField = user + + @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 [ResponsesClientEvent]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ResponsesClientEvent]. */ + class Builder internal constructor() { + + private var type: JsonValue = JsonValue.from("response.create") + 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() + private var instructions: JsonField = JsonMissing.of() + private var maxOutputTokens: JsonField = JsonMissing.of() + private var maxToolCalls: JsonField = JsonMissing.of() + private var metadata: JsonField = JsonMissing.of() + private var model: JsonField = JsonMissing.of() + private var parallelToolCalls: JsonField = JsonMissing.of() + private var previousResponseId: JsonField = JsonMissing.of() + private var prompt: JsonField = JsonMissing.of() + private var promptCacheKey: JsonField = JsonMissing.of() + private var promptCacheRetention: JsonField = JsonMissing.of() + private var reasoning: JsonField = JsonMissing.of() + private var safetyIdentifier: JsonField = JsonMissing.of() + private var serviceTier: JsonField = JsonMissing.of() + private var store: JsonField = JsonMissing.of() + private var stream: JsonField = JsonMissing.of() + private var streamOptions: JsonField = JsonMissing.of() + private var temperature: JsonField = JsonMissing.of() + private var text: JsonField = JsonMissing.of() + private var toolChoice: JsonField = JsonMissing.of() + private var tools: JsonField>? = null + private var topLogprobs: JsonField = JsonMissing.of() + private var topP: JsonField = JsonMissing.of() + private var truncation: JsonField = JsonMissing.of() + private var user: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(responsesClientEvent: ResponsesClientEvent) = apply { + type = responsesClientEvent.type + background = responsesClientEvent.background + contextManagement = responsesClientEvent.contextManagement.map { it.toMutableList() } + conversation = responsesClientEvent.conversation + include = responsesClientEvent.include.map { it.toMutableList() } + input = responsesClientEvent.input + instructions = responsesClientEvent.instructions + maxOutputTokens = responsesClientEvent.maxOutputTokens + maxToolCalls = responsesClientEvent.maxToolCalls + metadata = responsesClientEvent.metadata + model = responsesClientEvent.model + parallelToolCalls = responsesClientEvent.parallelToolCalls + previousResponseId = responsesClientEvent.previousResponseId + prompt = responsesClientEvent.prompt + promptCacheKey = responsesClientEvent.promptCacheKey + promptCacheRetention = responsesClientEvent.promptCacheRetention + reasoning = responsesClientEvent.reasoning + safetyIdentifier = responsesClientEvent.safetyIdentifier + serviceTier = responsesClientEvent.serviceTier + store = responsesClientEvent.store + stream = responsesClientEvent.stream + streamOptions = responsesClientEvent.streamOptions + temperature = responsesClientEvent.temperature + text = responsesClientEvent.text + toolChoice = responsesClientEvent.toolChoice + tools = responsesClientEvent.tools.map { it.toMutableList() } + topLogprobs = responsesClientEvent.topLogprobs + topP = responsesClientEvent.topP + truncation = responsesClientEvent.truncation + user = responsesClientEvent.user + additionalProperties = responsesClientEvent.additionalProperties.toMutableMap() + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("response.create") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** + * Whether to run the model response in the background. + * [Learn more](https://platform.openai.com/docs/guides/background). + */ + fun background(background: Boolean?) = background(JsonField.ofNullable(background)) + + /** + * Alias for [Builder.background]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun background(background: Boolean) = background(background as Boolean?) + + /** Alias for calling [Builder.background] with `background.orElse(null)`. */ + fun background(background: Optional) = background(background.getOrNull()) + + /** + * Sets [Builder.background] to an arbitrary JSON value. + * + * You should usually call [Builder.background] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + 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 from + * this response are automatically added to this conversation after this response completes. + */ + fun conversation(conversation: Conversation?) = + conversation(JsonField.ofNullable(conversation)) + + /** Alias for calling [Builder.conversation] with `conversation.orElse(null)`. */ + fun conversation(conversation: Optional) = + conversation(conversation.getOrNull()) + + /** + * Sets [Builder.conversation] to an arbitrary JSON value. + * + * You should usually call [Builder.conversation] with a well-typed [Conversation] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun conversation(conversation: JsonField) = apply { + this.conversation = conversation + } + + /** Alias for calling [conversation] with `Conversation.ofId(id)`. */ + fun conversation(id: String) = conversation(Conversation.ofId(id)) + + /** + * Alias for calling [conversation] with + * `Conversation.ofResponseConversationParam(responseConversationParam)`. + */ + fun conversation(responseConversationParam: ResponseConversationParam) = + conversation(Conversation.ofResponseConversationParam(responseConversationParam)) + + /** + * Specify additional output data to include in the model response. Currently supported + * values are: + * - `web_search_call.action.sources`: Include the sources of the web search tool call. + * - `code_interpreter_call.outputs`: Includes the outputs of python code execution in code + * interpreter tool call items. + * - `computer_call_output.output.image_url`: Include image urls from the computer call + * output. + * - `file_search_call.results`: Include the search results of the file search tool call. + * - `message.input_image.image_url`: Include image urls from the input message. + * - `message.output_text.logprobs`: Include logprobs with assistant messages. + * - `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in + * reasoning item outputs. This enables reasoning items to be used in multi-turn + * conversations when using the Responses API statelessly (like when the `store` parameter + * is set to `false`, or when an organization is enrolled in the zero data retention + * program). + */ + fun include(include: List?) = include(JsonField.ofNullable(include)) + + /** Alias for calling [Builder.include] with `include.orElse(null)`. */ + fun include(include: Optional>) = include(include.getOrNull()) + + /** + * Sets [Builder.include] to an arbitrary JSON value. + * + * You should usually call [Builder.include] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun include(include: JsonField>) = apply { + this.include = include.map { it.toMutableList() } + } + + /** + * Adds a single [ResponseIncludable] to [Builder.include]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addInclude(include: ResponseIncludable) = apply { + this.include = + (this.include ?: JsonField.of(mutableListOf())).also { + checkKnown("include", it).add(include) + } + } + + /** + * Text, image, or file inputs to the model, used to generate a response. + * + * Learn more: + * - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) + * - [Image inputs](https://platform.openai.com/docs/guides/images) + * - [File inputs](https://platform.openai.com/docs/guides/pdf-files) + * - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) + * - [Function calling](https://platform.openai.com/docs/guides/function-calling) + */ + fun input(input: Input) = input(JsonField.of(input)) + + /** + * Sets [Builder.input] to an arbitrary JSON value. + * + * You should usually call [Builder.input] with a well-typed [Input] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun input(input: JsonField) = apply { this.input = input } + + /** Alias for calling [input] with `Input.ofText(text)`. */ + fun input(text: String) = input(Input.ofText(text)) + + /** Alias for calling [input] with `Input.ofResponse(response)`. */ + fun inputOfResponse(response: List) = input(Input.ofResponse(response)) + + /** + * A system (or developer) message inserted into the model's context. + * + * When using along with `previous_response_id`, the instructions from a previous response + * will not be carried over to the next response. This makes it simple to swap out system + * (or developer) messages in new responses. + */ + fun instructions(instructions: String?) = instructions(JsonField.ofNullable(instructions)) + + /** Alias for calling [Builder.instructions] with `instructions.orElse(null)`. */ + fun instructions(instructions: Optional) = instructions(instructions.getOrNull()) + + /** + * Sets [Builder.instructions] to an arbitrary JSON value. + * + * You should usually call [Builder.instructions] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun instructions(instructions: JsonField) = apply { + this.instructions = instructions + } + + /** + * An upper bound for the number of tokens that can be generated for a response, including + * visible output tokens and + * [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). + */ + fun maxOutputTokens(maxOutputTokens: Long?) = + maxOutputTokens(JsonField.ofNullable(maxOutputTokens)) + + /** + * Alias for [Builder.maxOutputTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun maxOutputTokens(maxOutputTokens: Long) = maxOutputTokens(maxOutputTokens as Long?) + + /** Alias for calling [Builder.maxOutputTokens] with `maxOutputTokens.orElse(null)`. */ + fun maxOutputTokens(maxOutputTokens: Optional) = + maxOutputTokens(maxOutputTokens.getOrNull()) + + /** + * Sets [Builder.maxOutputTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.maxOutputTokens] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun maxOutputTokens(maxOutputTokens: JsonField) = apply { + this.maxOutputTokens = maxOutputTokens + } + + /** + * The maximum number of total calls to built-in tools that can be processed in a response. + * This maximum number applies across all built-in tool calls, not per individual tool. Any + * further attempts to call a tool by the model will be ignored. + */ + fun maxToolCalls(maxToolCalls: Long?) = maxToolCalls(JsonField.ofNullable(maxToolCalls)) + + /** + * Alias for [Builder.maxToolCalls]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun maxToolCalls(maxToolCalls: Long) = maxToolCalls(maxToolCalls as Long?) + + /** Alias for calling [Builder.maxToolCalls] with `maxToolCalls.orElse(null)`. */ + fun maxToolCalls(maxToolCalls: Optional) = maxToolCalls(maxToolCalls.getOrNull()) + + /** + * Sets [Builder.maxToolCalls] to an arbitrary JSON value. + * + * You should usually call [Builder.maxToolCalls] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun maxToolCalls(maxToolCalls: JsonField) = apply { this.maxToolCalls = maxToolCalls } + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for + * storing additional information about the object in a structured format, and querying for + * objects via API or the dashboard. + * + * Keys are strings with a maximum length of 64 characters. Values are strings with a + * maximum length of 512 characters. + */ + fun metadata(metadata: Metadata?) = metadata(JsonField.ofNullable(metadata)) + + /** Alias for calling [Builder.metadata] with `metadata.orElse(null)`. */ + fun metadata(metadata: Optional) = metadata(metadata.getOrNull()) + + /** + * Sets [Builder.metadata] to an arbitrary JSON value. + * + * You should usually call [Builder.metadata] with a well-typed [Metadata] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun metadata(metadata: JsonField) = apply { this.metadata = metadata } + + /** + * Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range + * of models with different capabilities, performance characteristics, and price points. + * Refer to the [model guide](https://platform.openai.com/docs/models) to browse and compare + * available models. + */ + fun model(model: ResponsesModel) = model(JsonField.of(model)) + + /** + * Sets [Builder.model] to an arbitrary JSON value. + * + * You should usually call [Builder.model] with a well-typed [ResponsesModel] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun model(model: JsonField) = apply { this.model = model } + + /** Alias for calling [model] with `ResponsesModel.ofString(string)`. */ + fun model(string: String) = model(ResponsesModel.ofString(string)) + + /** Alias for calling [model] with `ResponsesModel.ofChat(chat)`. */ + fun model(chat: ChatModel) = model(ResponsesModel.ofChat(chat)) + + /** Alias for calling [model] with `ResponsesModel.ofOnly(only)`. */ + fun model(only: ResponsesModel.ResponsesOnlyModel) = model(ResponsesModel.ofOnly(only)) + + /** Whether to allow the model to run tool calls in parallel. */ + fun parallelToolCalls(parallelToolCalls: Boolean?) = + parallelToolCalls(JsonField.ofNullable(parallelToolCalls)) + + /** + * Alias for [Builder.parallelToolCalls]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun parallelToolCalls(parallelToolCalls: Boolean) = + parallelToolCalls(parallelToolCalls as Boolean?) + + /** Alias for calling [Builder.parallelToolCalls] with `parallelToolCalls.orElse(null)`. */ + fun parallelToolCalls(parallelToolCalls: Optional) = + parallelToolCalls(parallelToolCalls.getOrNull()) + + /** + * Sets [Builder.parallelToolCalls] to an arbitrary JSON value. + * + * You should usually call [Builder.parallelToolCalls] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun parallelToolCalls(parallelToolCalls: JsonField) = apply { + this.parallelToolCalls = parallelToolCalls + } + + /** + * The unique ID of the previous response to the model. Use this to create multi-turn + * conversations. Learn more about + * [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot + * be used in conjunction with `conversation`. + */ + fun previousResponseId(previousResponseId: String?) = + previousResponseId(JsonField.ofNullable(previousResponseId)) + + /** + * Alias for calling [Builder.previousResponseId] with `previousResponseId.orElse(null)`. + */ + fun previousResponseId(previousResponseId: Optional) = + previousResponseId(previousResponseId.getOrNull()) + + /** + * Sets [Builder.previousResponseId] to an arbitrary JSON value. + * + * You should usually call [Builder.previousResponseId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun previousResponseId(previousResponseId: JsonField) = apply { + this.previousResponseId = previousResponseId + } + + /** + * Reference to a prompt template and its variables. + * [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). + */ + fun prompt(prompt: ResponsePrompt?) = prompt(JsonField.ofNullable(prompt)) + + /** Alias for calling [Builder.prompt] with `prompt.orElse(null)`. */ + fun prompt(prompt: Optional) = prompt(prompt.getOrNull()) + + /** + * Sets [Builder.prompt] to an arbitrary JSON value. + * + * You should usually call [Builder.prompt] with a well-typed [ResponsePrompt] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun prompt(prompt: JsonField) = apply { this.prompt = prompt } + + /** + * Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. + * Replaces the `user` field. + * [Learn more](https://platform.openai.com/docs/guides/prompt-caching). + */ + fun promptCacheKey(promptCacheKey: String) = promptCacheKey(JsonField.of(promptCacheKey)) + + /** + * Sets [Builder.promptCacheKey] to an arbitrary JSON value. + * + * You should usually call [Builder.promptCacheKey] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun promptCacheKey(promptCacheKey: JsonField) = apply { + this.promptCacheKey = promptCacheKey + } + + /** + * The retention policy for the prompt cache. Set to `24h` to enable extended prompt + * caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. + * [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). + */ + fun promptCacheRetention(promptCacheRetention: PromptCacheRetention?) = + promptCacheRetention(JsonField.ofNullable(promptCacheRetention)) + + /** + * Alias for calling [Builder.promptCacheRetention] with + * `promptCacheRetention.orElse(null)`. + */ + fun promptCacheRetention(promptCacheRetention: Optional) = + promptCacheRetention(promptCacheRetention.getOrNull()) + + /** + * Sets [Builder.promptCacheRetention] to an arbitrary JSON value. + * + * You should usually call [Builder.promptCacheRetention] with a well-typed + * [PromptCacheRetention] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun promptCacheRetention(promptCacheRetention: JsonField) = apply { + this.promptCacheRetention = promptCacheRetention + } + + /** + * **gpt-5 and o-series models only** + * + * Configuration options for + * [reasoning models](https://platform.openai.com/docs/guides/reasoning). + */ + fun reasoning(reasoning: Reasoning?) = reasoning(JsonField.ofNullable(reasoning)) + + /** Alias for calling [Builder.reasoning] with `reasoning.orElse(null)`. */ + fun reasoning(reasoning: Optional) = reasoning(reasoning.getOrNull()) + + /** + * Sets [Builder.reasoning] to an arbitrary JSON value. + * + * You should usually call [Builder.reasoning] with a well-typed [Reasoning] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun reasoning(reasoning: JsonField) = apply { this.reasoning = reasoning } + + /** + * A stable identifier used to help detect users of your application that may be violating + * OpenAI's usage policies. The IDs should be a string that uniquely identifies each user, + * with a maximum length of 64 characters. We recommend hashing their username or email + * address, in order to avoid sending us any identifying information. + * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). + */ + fun safetyIdentifier(safetyIdentifier: String) = + safetyIdentifier(JsonField.of(safetyIdentifier)) + + /** + * Sets [Builder.safetyIdentifier] to an arbitrary JSON value. + * + * You should usually call [Builder.safetyIdentifier] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun safetyIdentifier(safetyIdentifier: JsonField) = apply { + this.safetyIdentifier = safetyIdentifier + } + + /** + * Specifies the processing type used for serving the request. + * - If set to 'auto', then the request will be processed with the service tier configured + * in the Project settings. Unless otherwise configured, the Project will use 'default'. + * - If set to 'default', then the request will be processed with the standard pricing and + * performance for the selected model. + * - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or + * '[priority](https://openai.com/api-priority-processing/)', then the request will be + * processed with the corresponding service tier. + * - When not set, the default behavior is 'auto'. + * + * When the `service_tier` parameter is set, the response body will include the + * `service_tier` value based on the processing mode actually used to serve the request. + * This response value may be different from the value set in the parameter. + */ + fun serviceTier(serviceTier: ServiceTier?) = serviceTier(JsonField.ofNullable(serviceTier)) + + /** Alias for calling [Builder.serviceTier] with `serviceTier.orElse(null)`. */ + fun serviceTier(serviceTier: Optional) = serviceTier(serviceTier.getOrNull()) + + /** + * Sets [Builder.serviceTier] to an arbitrary JSON value. + * + * You should usually call [Builder.serviceTier] with a well-typed [ServiceTier] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun serviceTier(serviceTier: JsonField) = apply { + this.serviceTier = serviceTier + } + + /** Whether to store the generated model response for later retrieval via API. */ + fun store(store: Boolean?) = store(JsonField.ofNullable(store)) + + /** + * Alias for [Builder.store]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun store(store: Boolean) = store(store as Boolean?) + + /** Alias for calling [Builder.store] with `store.orElse(null)`. */ + fun store(store: Optional) = store(store.getOrNull()) + + /** + * Sets [Builder.store] to an arbitrary JSON value. + * + * You should usually call [Builder.store] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun store(store: JsonField) = apply { this.store = store } + + /** + * If set to true, the model response data will be streamed to the client as it is generated + * using + * [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). + * See the + * [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) + * for more information. + */ + fun stream(stream: Boolean?) = stream(JsonField.ofNullable(stream)) + + /** + * Alias for [Builder.stream]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun stream(stream: Boolean) = stream(stream as Boolean?) + + /** Alias for calling [Builder.stream] with `stream.orElse(null)`. */ + fun stream(stream: Optional) = stream(stream.getOrNull()) + + /** + * Sets [Builder.stream] to an arbitrary JSON value. + * + * You should usually call [Builder.stream] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun stream(stream: JsonField) = apply { this.stream = stream } + + /** Options for streaming responses. Only set this when you set `stream: true`. */ + fun streamOptions(streamOptions: StreamOptions?) = + streamOptions(JsonField.ofNullable(streamOptions)) + + /** Alias for calling [Builder.streamOptions] with `streamOptions.orElse(null)`. */ + fun streamOptions(streamOptions: Optional) = + streamOptions(streamOptions.getOrNull()) + + /** + * Sets [Builder.streamOptions] to an arbitrary JSON value. + * + * You should usually call [Builder.streamOptions] with a well-typed [StreamOptions] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun streamOptions(streamOptions: JsonField) = apply { + this.streamOptions = streamOptions + } + + /** + * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the + * output more random, while lower values like 0.2 will make it more focused and + * deterministic. We generally recommend altering this or `top_p` but not both. + */ + fun temperature(temperature: Double?) = temperature(JsonField.ofNullable(temperature)) + + /** + * Alias for [Builder.temperature]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun temperature(temperature: Double) = temperature(temperature as Double?) + + /** Alias for calling [Builder.temperature] with `temperature.orElse(null)`. */ + fun temperature(temperature: Optional) = temperature(temperature.getOrNull()) + + /** + * Sets [Builder.temperature] to an arbitrary JSON value. + * + * You should usually call [Builder.temperature] with a well-typed [Double] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun temperature(temperature: JsonField) = apply { this.temperature = temperature } + + /** + * Configuration options for a text response from the model. Can be plain text or structured + * JSON data. Learn more: + * - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) + * - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) + */ + fun text(text: ResponseTextConfig) = text(JsonField.of(text)) + + /** + * Sets [Builder.text] to an arbitrary JSON value. + * + * You should usually call [Builder.text] with a well-typed [ResponseTextConfig] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun text(text: JsonField) = apply { this.text = text } + + /** + * How the model should select which tool (or tools) to use when generating a response. See + * the `tools` parameter to see how to specify which tools the model can call. + */ + fun toolChoice(toolChoice: ToolChoice) = toolChoice(JsonField.of(toolChoice)) + + /** + * Sets [Builder.toolChoice] to an arbitrary JSON value. + * + * You should usually call [Builder.toolChoice] with a well-typed [ToolChoice] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun toolChoice(toolChoice: JsonField) = apply { this.toolChoice = toolChoice } + + /** Alias for calling [toolChoice] with `ToolChoice.ofOptions(options)`. */ + fun toolChoice(options: ToolChoiceOptions) = toolChoice(ToolChoice.ofOptions(options)) + + /** Alias for calling [toolChoice] with `ToolChoice.ofAllowed(allowed)`. */ + fun toolChoice(allowed: ToolChoiceAllowed) = toolChoice(ToolChoice.ofAllowed(allowed)) + + /** Alias for calling [toolChoice] with `ToolChoice.ofTypes(types)`. */ + fun toolChoice(types: ToolChoiceTypes) = toolChoice(ToolChoice.ofTypes(types)) + + /** Alias for calling [toolChoice] with `ToolChoice.ofFunction(function)`. */ + fun toolChoice(function: ToolChoiceFunction) = toolChoice(ToolChoice.ofFunction(function)) + + /** Alias for calling [toolChoice] with `ToolChoice.ofMcp(mcp)`. */ + fun toolChoice(mcp: ToolChoiceMcp) = toolChoice(ToolChoice.ofMcp(mcp)) + + /** Alias for calling [toolChoice] with `ToolChoice.ofCustom(custom)`. */ + fun toolChoice(custom: ToolChoiceCustom) = toolChoice(ToolChoice.ofCustom(custom)) + + /** Alias for calling [toolChoice] with `ToolChoice.ofApplyPatch(applyPatch)`. */ + fun toolChoice(applyPatch: ToolChoiceApplyPatch) = + toolChoice(ToolChoice.ofApplyPatch(applyPatch)) + + /** Alias for calling [toolChoice] with `ToolChoice.ofShell(shell)`. */ + fun toolChoice(shell: ToolChoiceShell) = toolChoice(ToolChoice.ofShell(shell)) + + /** + * An array of tools the model may call while generating a response. You can specify which + * tool to use by setting the `tool_choice` parameter. + * + * We support the following categories of tools: + * - **Built-in tools**: Tools that are provided by OpenAI that extend the model's + * capabilities, like + * [web search](https://platform.openai.com/docs/guides/tools-web-search) or + * [file search](https://platform.openai.com/docs/guides/tools-file-search). Learn more + * about [built-in tools](https://platform.openai.com/docs/guides/tools). + * - **MCP Tools**: Integrations with third-party systems via custom MCP servers or + * predefined connectors such as Google Drive and SharePoint. Learn more about + * [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). + * - **Function calls (custom tools)**: Functions that are defined by you, enabling the + * model to call your own code with strongly typed arguments and outputs. Learn more about + * [function calling](https://platform.openai.com/docs/guides/function-calling). You can + * also use custom tools to call your own code. + */ + fun tools(tools: List) = tools(JsonField.of(tools)) + + /** + * Sets [Builder.tools] to an arbitrary JSON value. + * + * You should usually call [Builder.tools] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } + + /** + * Adds a single [Tool] to [tools]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTool(tool: Tool) = apply { + tools = + (tools ?: JsonField.of(mutableListOf())).also { checkKnown("tools", it).add(tool) } + } + + /** Alias for calling [addTool] with `Tool.ofFunction(function)`. */ + fun addTool(function: FunctionTool) = addTool(Tool.ofFunction(function)) + + /** Alias for calling [addTool] with `Tool.ofFileSearch(fileSearch)`. */ + fun addTool(fileSearch: FileSearchTool) = addTool(Tool.ofFileSearch(fileSearch)) + + /** + * Alias for calling [addTool] with the following: + * ```java + * FileSearchTool.builder() + * .vectorStoreIds(vectorStoreIds) + * .build() + * ``` + */ + fun addFileSearchTool(vectorStoreIds: List) = + addTool(FileSearchTool.builder().vectorStoreIds(vectorStoreIds).build()) + + /** Alias for calling [addTool] with `Tool.ofComputerUsePreview(computerUsePreview)`. */ + fun addTool(computerUsePreview: ComputerTool) = + addTool(Tool.ofComputerUsePreview(computerUsePreview)) + + /** Alias for calling [addTool] with `Tool.ofWebSearch(webSearch)`. */ + fun addTool(webSearch: WebSearchTool) = addTool(Tool.ofWebSearch(webSearch)) + + /** Alias for calling [addTool] with `Tool.ofMcp(mcp)`. */ + fun addTool(mcp: Tool.Mcp) = addTool(Tool.ofMcp(mcp)) + + /** + * Alias for calling [addTool] with the following: + * ```java + * Tool.Mcp.builder() + * .serverLabel(serverLabel) + * .build() + * ``` + */ + fun addMcpTool(serverLabel: String) = + addTool(Tool.Mcp.builder().serverLabel(serverLabel).build()) + + /** Alias for calling [addTool] with `Tool.ofCodeInterpreter(codeInterpreter)`. */ + fun addTool(codeInterpreter: Tool.CodeInterpreter) = + addTool(Tool.ofCodeInterpreter(codeInterpreter)) + + /** + * Alias for calling [addTool] with the following: + * ```java + * Tool.CodeInterpreter.builder() + * .container(container) + * .build() + * ``` + */ + fun addCodeInterpreterTool(container: Tool.CodeInterpreter.Container) = + addTool(Tool.CodeInterpreter.builder().container(container).build()) + + /** + * Alias for calling [addCodeInterpreterTool] with + * `Tool.CodeInterpreter.Container.ofString(string)`. + */ + fun addCodeInterpreterTool(string: String) = + addCodeInterpreterTool(Tool.CodeInterpreter.Container.ofString(string)) + + /** + * Alias for calling [addCodeInterpreterTool] with + * `Tool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto)`. + */ + fun addCodeInterpreterTool( + codeInterpreterToolAuto: Tool.CodeInterpreter.Container.CodeInterpreterToolAuto + ) = + addCodeInterpreterTool( + Tool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto) + ) + + /** Alias for calling [addTool] with `Tool.ofImageGeneration(imageGeneration)`. */ + fun addTool(imageGeneration: Tool.ImageGeneration) = + addTool(Tool.ofImageGeneration(imageGeneration)) + + /** Alias for calling [addTool] with `Tool.ofLocalShell()`. */ + fun addToolLocalShell() = addTool(Tool.ofLocalShell()) + + /** Alias for calling [addTool] with `Tool.ofShell(shell)`. */ + fun addTool(shell: FunctionShellTool) = addTool(Tool.ofShell(shell)) + + /** Alias for calling [addTool] with `Tool.ofCustom(custom)`. */ + fun addTool(custom: CustomTool) = addTool(Tool.ofCustom(custom)) + + /** + * Alias for calling [addTool] with the following: + * ```java + * CustomTool.builder() + * .name(name) + * .build() + * ``` + */ + fun addCustomTool(name: String) = addTool(CustomTool.builder().name(name).build()) + + /** Alias for calling [addTool] with `Tool.ofWebSearchPreview(webSearchPreview)`. */ + fun addTool(webSearchPreview: WebSearchPreviewTool) = + addTool(Tool.ofWebSearchPreview(webSearchPreview)) + + /** Alias for calling [addTool] with `Tool.ofApplyPatch(applyPatch)`. */ + fun addTool(applyPatch: ApplyPatchTool) = addTool(Tool.ofApplyPatch(applyPatch)) + + /** + * An integer between 0 and 20 specifying the number of most likely tokens to return at each + * token position, each with an associated log probability. + */ + fun topLogprobs(topLogprobs: Long?) = topLogprobs(JsonField.ofNullable(topLogprobs)) + + /** + * Alias for [Builder.topLogprobs]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun topLogprobs(topLogprobs: Long) = topLogprobs(topLogprobs as Long?) + + /** Alias for calling [Builder.topLogprobs] with `topLogprobs.orElse(null)`. */ + fun topLogprobs(topLogprobs: Optional) = topLogprobs(topLogprobs.getOrNull()) + + /** + * Sets [Builder.topLogprobs] to an arbitrary JSON value. + * + * You should usually call [Builder.topLogprobs] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun topLogprobs(topLogprobs: JsonField) = apply { this.topLogprobs = topLogprobs } + + /** + * An alternative to sampling with temperature, called nucleus sampling, where the model + * considers the results of the tokens with top_p probability mass. So 0.1 means only the + * tokens comprising the top 10% probability mass are considered. + * + * We generally recommend altering this or `temperature` but not both. + */ + fun topP(topP: Double?) = topP(JsonField.ofNullable(topP)) + + /** + * Alias for [Builder.topP]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun topP(topP: Double) = topP(topP as Double?) + + /** Alias for calling [Builder.topP] with `topP.orElse(null)`. */ + fun topP(topP: Optional) = topP(topP.getOrNull()) + + /** + * Sets [Builder.topP] to an arbitrary JSON value. + * + * You should usually call [Builder.topP] with a well-typed [Double] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun topP(topP: JsonField) = apply { this.topP = topP } + + /** + * The truncation strategy to use for the model response. + * - `auto`: If the input to this Response exceeds the model's context window size, the + * model will truncate the response to fit the context window by dropping items from the + * beginning of the conversation. + * - `disabled` (default): If the input size will exceed the context window size for a + * model, the request will fail with a 400 error. + */ + fun truncation(truncation: Truncation?) = truncation(JsonField.ofNullable(truncation)) + + /** Alias for calling [Builder.truncation] with `truncation.orElse(null)`. */ + fun truncation(truncation: Optional) = truncation(truncation.getOrNull()) + + /** + * Sets [Builder.truncation] to an arbitrary JSON value. + * + * You should usually call [Builder.truncation] with a well-typed [Truncation] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun truncation(truncation: JsonField) = apply { this.truncation = truncation } + + /** + * This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use + * `prompt_cache_key` instead to maintain caching optimizations. A stable identifier for + * your end-users. Used to boost cache hit rates by better bucketing similar requests and to + * help OpenAI detect and prevent abuse. + * [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). + */ + @Deprecated("deprecated") fun user(user: String) = user(JsonField.of(user)) + + /** + * Sets [Builder.user] to an arbitrary JSON value. + * + * You should usually call [Builder.user] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + @Deprecated("deprecated") fun user(user: JsonField) = apply { this.user = user } + + 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 [ResponsesClientEvent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): ResponsesClientEvent = + ResponsesClientEvent( + type, + background, + (contextManagement ?: JsonMissing.of()).map { it.toImmutable() }, + conversation, + (include ?: JsonMissing.of()).map { it.toImmutable() }, + input, + instructions, + maxOutputTokens, + maxToolCalls, + metadata, + model, + parallelToolCalls, + previousResponseId, + prompt, + promptCacheKey, + promptCacheRetention, + reasoning, + safetyIdentifier, + serviceTier, + store, + stream, + streamOptions, + temperature, + text, + toolChoice, + (tools ?: JsonMissing.of()).map { it.toImmutable() }, + topLogprobs, + topP, + truncation, + user, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ResponsesClientEvent = apply { + if (validated) { + return@apply + } + + _type().let { + if (it != JsonValue.from("response.create")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + background() + contextManagement().ifPresent { it.forEach { it.validate() } } + conversation().ifPresent { it.validate() } + include().ifPresent { it.forEach { it.validate() } } + input().ifPresent { it.validate() } + instructions() + maxOutputTokens() + maxToolCalls() + metadata().ifPresent { it.validate() } + model().ifPresent { it.validate() } + parallelToolCalls() + previousResponseId() + prompt().ifPresent { it.validate() } + promptCacheKey() + promptCacheRetention().ifPresent { it.validate() } + reasoning().ifPresent { it.validate() } + safetyIdentifier() + serviceTier().ifPresent { it.validate() } + store() + stream() + streamOptions().ifPresent { it.validate() } + temperature() + text().ifPresent { it.validate() } + toolChoice().ifPresent { it.validate() } + tools().ifPresent { it.forEach { it.validate() } } + topLogprobs() + topP() + truncation().ifPresent { it.validate() } + user() + 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 = + type.let { if (it == JsonValue.from("response.create")) 1 else 0 } + + (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) + + (if (instructions.asKnown().isPresent) 1 else 0) + + (if (maxOutputTokens.asKnown().isPresent) 1 else 0) + + (if (maxToolCalls.asKnown().isPresent) 1 else 0) + + (metadata.asKnown().getOrNull()?.validity() ?: 0) + + (model.asKnown().getOrNull()?.validity() ?: 0) + + (if (parallelToolCalls.asKnown().isPresent) 1 else 0) + + (if (previousResponseId.asKnown().isPresent) 1 else 0) + + (prompt.asKnown().getOrNull()?.validity() ?: 0) + + (if (promptCacheKey.asKnown().isPresent) 1 else 0) + + (promptCacheRetention.asKnown().getOrNull()?.validity() ?: 0) + + (reasoning.asKnown().getOrNull()?.validity() ?: 0) + + (if (safetyIdentifier.asKnown().isPresent) 1 else 0) + + (serviceTier.asKnown().getOrNull()?.validity() ?: 0) + + (if (store.asKnown().isPresent) 1 else 0) + + (if (stream.asKnown().isPresent) 1 else 0) + + (streamOptions.asKnown().getOrNull()?.validity() ?: 0) + + (if (temperature.asKnown().isPresent) 1 else 0) + + (text.asKnown().getOrNull()?.validity() ?: 0) + + (toolChoice.asKnown().getOrNull()?.validity() ?: 0) + + (tools.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (topLogprobs.asKnown().isPresent) 1 else 0) + + (if (topP.asKnown().isPresent) 1 else 0) + + (truncation.asKnown().getOrNull()?.validity() ?: 0) + + (if (user.asKnown().isPresent) 1 else 0) + + 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}" + } + + /** + * 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 + * automatically added to this conversation after this response completes. + */ + @JsonDeserialize(using = Conversation.Deserializer::class) + @JsonSerialize(using = Conversation.Serializer::class) + class Conversation + private constructor( + private val id: String? = null, + private val responseConversationParam: ResponseConversationParam? = null, + private val _json: JsonValue? = null, + ) { + + /** The unique ID of the conversation. */ + fun id(): Optional = Optional.ofNullable(id) + + /** The conversation that this response belongs to. */ + fun responseConversationParam(): Optional = + Optional.ofNullable(responseConversationParam) + + fun isId(): Boolean = id != null + + fun isResponseConversationParam(): Boolean = responseConversationParam != null + + /** The unique ID of the conversation. */ + fun asId(): String = id.getOrThrow("id") + + /** The conversation that this response belongs to. */ + fun asResponseConversationParam(): ResponseConversationParam = + responseConversationParam.getOrThrow("responseConversationParam") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + id != null -> visitor.visitId(id) + responseConversationParam != null -> + visitor.visitResponseConversationParam(responseConversationParam) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Conversation = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitId(id: String) {} + + override fun visitResponseConversationParam( + responseConversationParam: ResponseConversationParam + ) { + responseConversationParam.validate() + } + } + ) + 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 = + accept( + object : Visitor { + override fun visitId(id: String) = 1 + + override fun visitResponseConversationParam( + responseConversationParam: ResponseConversationParam + ) = responseConversationParam.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Conversation && + id == other.id && + responseConversationParam == other.responseConversationParam + } + + override fun hashCode(): Int = Objects.hash(id, responseConversationParam) + + override fun toString(): String = + when { + id != null -> "Conversation{id=$id}" + responseConversationParam != null -> + "Conversation{responseConversationParam=$responseConversationParam}" + _json != null -> "Conversation{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Conversation") + } + + companion object { + + /** The unique ID of the conversation. */ + @JvmStatic fun ofId(id: String) = Conversation(id = id) + + /** The conversation that this response belongs to. */ + @JvmStatic + fun ofResponseConversationParam(responseConversationParam: ResponseConversationParam) = + Conversation(responseConversationParam = responseConversationParam) + } + + /** + * An interface that defines how to map each variant of [Conversation] to a value of type + * [T]. + */ + interface Visitor { + + /** The unique ID of the conversation. */ + fun visitId(id: String): T + + /** The conversation that this response belongs to. */ + fun visitResponseConversationParam( + responseConversationParam: ResponseConversationParam + ): T + + /** + * Maps an unknown variant of [Conversation] to a value of type [T]. + * + * An instance of [Conversation] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the SDK + * is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Conversation: $json") + } + } + + internal class Deserializer : BaseDeserializer(Conversation::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Conversation { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Conversation(responseConversationParam = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Conversation(id = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from boolean). + 0 -> Conversation(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Conversation::class) { + + override fun serialize( + value: Conversation, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.id != null -> generator.writeObject(value.id) + value.responseConversationParam != null -> + generator.writeObject(value.responseConversationParam) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Conversation") + } + } + } + } + + /** + * Text, image, or file inputs to the model, used to generate a response. + * + * Learn more: + * - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) + * - [Image inputs](https://platform.openai.com/docs/guides/images) + * - [File inputs](https://platform.openai.com/docs/guides/pdf-files) + * - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) + * - [Function calling](https://platform.openai.com/docs/guides/function-calling) + */ + @JsonDeserialize(using = Input.Deserializer::class) + @JsonSerialize(using = Input.Serializer::class) + class Input + private constructor( + private val text: String? = null, + private val response: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A text input to the model, equivalent to a text input with the `user` role. */ + fun text(): Optional = Optional.ofNullable(text) + + /** A list of one or many input items to the model, containing different content types. */ + fun response(): Optional> = Optional.ofNullable(response) + + fun isText(): Boolean = text != null + + fun isResponse(): Boolean = response != null + + /** A text input to the model, equivalent to a text input with the `user` role. */ + fun asText(): String = text.getOrThrow("text") + + /** A list of one or many input items to the model, containing different content types. */ + fun asResponse(): List = response.getOrThrow("response") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + text != null -> visitor.visitText(text) + response != null -> visitor.visitResponse(response) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Input = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitText(text: String) {} + + override fun visitResponse(response: List) { + response.forEach { it.validate() } + } + } + ) + 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 = + accept( + object : Visitor { + override fun visitText(text: String) = 1 + + override fun visitResponse(response: List) = + response.sumOf { it.validity().toInt() } + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Input && text == other.text && response == other.response + } + + override fun hashCode(): Int = Objects.hash(text, response) + + override fun toString(): String = + when { + text != null -> "Input{text=$text}" + response != null -> "Input{response=$response}" + _json != null -> "Input{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Input") + } + + companion object { + + /** A text input to the model, equivalent to a text input with the `user` role. */ + @JvmStatic fun ofText(text: String) = Input(text = text) + + /** + * A list of one or many input items to the model, containing different content types. + */ + @JvmStatic + fun ofResponse(response: List) = + Input(response = response.toImmutable()) + } + + /** An interface that defines how to map each variant of [Input] to a value of type [T]. */ + interface Visitor { + + /** A text input to the model, equivalent to a text input with the `user` role. */ + fun visitText(text: String): T + + /** + * A list of one or many input items to the model, containing different content types. + */ + fun visitResponse(response: List): T + + /** + * Maps an unknown variant of [Input] to a value of type [T]. + * + * An instance of [Input] can contain an unknown variant if it was deserialized from + * data that doesn't match any known variant. For example, if the SDK is on an older + * version than the API, then the API may respond with new variants that the SDK is + * unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Input: $json") + } + } + + internal class Deserializer : BaseDeserializer(Input::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Input { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Input(text = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>())?.let { + Input(response = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from boolean). + 0 -> Input(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Input::class) { + + override fun serialize( + value: Input, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.text != null -> generator.writeObject(value.text) + value.response != null -> generator.writeObject(value.response) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Input") + } + } + } + } + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format, and querying for objects via + * API or the dashboard. + * + * Keys are strings with a maximum length of 64 characters. Values are strings with a maximum + * length of 512 characters. + */ + class Metadata + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Metadata]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Metadata]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(metadata: Metadata) = apply { + additionalProperties = metadata.additionalProperties.toMutableMap() + } + + 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 [Metadata]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Metadata = Metadata(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + fun validate(): Metadata = apply { + if (validated) { + return@apply + } + + 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 = + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Metadata && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Metadata{additionalProperties=$additionalProperties}" + } + + /** + * The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, + * which keeps cached prefixes active for longer, up to a maximum of 24 hours. + * [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). + */ + class PromptCacheRetention + @JsonCreator + private constructor(private val value: JsonField) : 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 = value + + companion object { + + @JvmField val IN_MEMORY = of("in-memory") + + @JvmField val _24H = of("24h") + + @JvmStatic fun of(value: String) = PromptCacheRetention(JsonField.of(value)) + } + + /** An enum containing [PromptCacheRetention]'s known values. */ + enum class Known { + IN_MEMORY, + _24H, + } + + /** + * An enum containing [PromptCacheRetention]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [PromptCacheRetention] 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 { + IN_MEMORY, + _24H, + /** + * An enum member indicating that [PromptCacheRetention] 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) { + IN_MEMORY -> Value.IN_MEMORY + _24H -> Value._24H + 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) { + IN_MEMORY -> Known.IN_MEMORY + _24H -> Known._24H + else -> throw OpenAIInvalidDataException("Unknown PromptCacheRetention: $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(): PromptCacheRetention = 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 PromptCacheRetention && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Specifies the processing type used for serving the request. + * - If set to 'auto', then the request will be processed with the service tier configured in + * the Project settings. Unless otherwise configured, the Project will use 'default'. + * - If set to 'default', then the request will be processed with the standard pricing and + * performance for the selected model. + * - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or + * '[priority](https://openai.com/api-priority-processing/)', then the request will be + * processed with the corresponding service tier. + * - When not set, the default behavior is 'auto'. + * + * When the `service_tier` parameter is set, the response body will include the `service_tier` + * value based on the processing mode actually used to serve the request. This response value + * may be different from the value set in the parameter. + */ + class ServiceTier @JsonCreator private constructor(private val value: JsonField) : + 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 = value + + companion object { + + @JvmField val AUTO = of("auto") + + @JvmField val DEFAULT = of("default") + + @JvmField val FLEX = of("flex") + + @JvmField val SCALE = of("scale") + + @JvmField val PRIORITY = of("priority") + + @JvmStatic fun of(value: String) = ServiceTier(JsonField.of(value)) + } + + /** An enum containing [ServiceTier]'s known values. */ + enum class Known { + AUTO, + DEFAULT, + FLEX, + SCALE, + PRIORITY, + } + + /** + * An enum containing [ServiceTier]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ServiceTier] 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 { + AUTO, + DEFAULT, + FLEX, + SCALE, + PRIORITY, + /** + * An enum member indicating that [ServiceTier] 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) { + AUTO -> Value.AUTO + DEFAULT -> Value.DEFAULT + FLEX -> Value.FLEX + SCALE -> Value.SCALE + PRIORITY -> Value.PRIORITY + 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) { + AUTO -> Known.AUTO + DEFAULT -> Known.DEFAULT + FLEX -> Known.FLEX + SCALE -> Known.SCALE + PRIORITY -> Known.PRIORITY + else -> throw OpenAIInvalidDataException("Unknown ServiceTier: $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(): ServiceTier = 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 ServiceTier && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Options for streaming responses. Only set this when you set `stream: true`. */ + class StreamOptions + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val includeObfuscation: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("include_obfuscation") + @ExcludeMissing + includeObfuscation: JsonField = JsonMissing.of() + ) : this(includeObfuscation, mutableMapOf()) + + /** + * When true, stream obfuscation will be enabled. Stream obfuscation adds random characters + * to an `obfuscation` field on streaming delta events to normalize payload sizes as a + * mitigation to certain side-channel attacks. These obfuscation fields are included by + * default, but add a small amount of overhead to the data stream. You can set + * `include_obfuscation` to false to optimize for bandwidth if you trust the network links + * between your application and the OpenAI API. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun includeObfuscation(): Optional = + includeObfuscation.getOptional("include_obfuscation") + + /** + * Returns the raw JSON value of [includeObfuscation]. + * + * Unlike [includeObfuscation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("include_obfuscation") + @ExcludeMissing + fun _includeObfuscation(): JsonField = includeObfuscation + + @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 [StreamOptions]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [StreamOptions]. */ + class Builder internal constructor() { + + private var includeObfuscation: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(streamOptions: StreamOptions) = apply { + includeObfuscation = streamOptions.includeObfuscation + additionalProperties = streamOptions.additionalProperties.toMutableMap() + } + + /** + * When true, stream obfuscation will be enabled. Stream obfuscation adds random + * characters to an `obfuscation` field on streaming delta events to normalize payload + * sizes as a mitigation to certain side-channel attacks. These obfuscation fields are + * included by default, but add a small amount of overhead to the data stream. You can + * set `include_obfuscation` to false to optimize for bandwidth if you trust the network + * links between your application and the OpenAI API. + */ + fun includeObfuscation(includeObfuscation: Boolean) = + includeObfuscation(JsonField.of(includeObfuscation)) + + /** + * Sets [Builder.includeObfuscation] to an arbitrary JSON value. + * + * You should usually call [Builder.includeObfuscation] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun includeObfuscation(includeObfuscation: JsonField) = apply { + this.includeObfuscation = includeObfuscation + } + + 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 [StreamOptions]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): StreamOptions = + StreamOptions(includeObfuscation, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): StreamOptions = apply { + if (validated) { + return@apply + } + + includeObfuscation() + 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 (includeObfuscation.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is StreamOptions && + includeObfuscation == other.includeObfuscation && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(includeObfuscation, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "StreamOptions{includeObfuscation=$includeObfuscation, additionalProperties=$additionalProperties}" + } + + /** + * How the model should select which tool (or tools) to use when generating a response. See the + * `tools` parameter to see how to specify which tools the model can call. + */ + @JsonDeserialize(using = ToolChoice.Deserializer::class) + @JsonSerialize(using = ToolChoice.Serializer::class) + class ToolChoice + private constructor( + private val options: ToolChoiceOptions? = null, + private val allowed: ToolChoiceAllowed? = null, + private val types: ToolChoiceTypes? = null, + private val function: ToolChoiceFunction? = null, + private val mcp: ToolChoiceMcp? = null, + private val custom: ToolChoiceCustom? = null, + private val applyPatch: ToolChoiceApplyPatch? = null, + private val shell: ToolChoiceShell? = null, + private val _json: JsonValue? = null, + ) { + + /** + * Controls which (if any) tool is called by the model. + * + * `none` means the model will not call any tool and instead generates a message. + * + * `auto` means the model can pick between generating a message or calling one or more + * tools. + * + * `required` means the model must call one or more tools. + */ + fun options(): Optional = Optional.ofNullable(options) + + /** Constrains the tools available to the model to a pre-defined set. */ + fun allowed(): Optional = Optional.ofNullable(allowed) + + /** + * Indicates that the model should use a built-in tool to generate a response. + * [Learn more about built-in tools](https://platform.openai.com/docs/guides/tools). + */ + fun types(): Optional = Optional.ofNullable(types) + + /** Use this option to force the model to call a specific function. */ + fun function(): Optional = Optional.ofNullable(function) + + /** Use this option to force the model to call a specific tool on a remote MCP server. */ + fun mcp(): Optional = Optional.ofNullable(mcp) + + /** Use this option to force the model to call a specific custom tool. */ + fun custom(): Optional = Optional.ofNullable(custom) + + /** Forces the model to call the apply_patch tool when executing a tool call. */ + fun applyPatch(): Optional = Optional.ofNullable(applyPatch) + + /** Forces the model to call the shell tool when a tool call is required. */ + fun shell(): Optional = Optional.ofNullable(shell) + + fun isOptions(): Boolean = options != null + + fun isAllowed(): Boolean = allowed != null + + fun isTypes(): Boolean = types != null + + fun isFunction(): Boolean = function != null + + fun isMcp(): Boolean = mcp != null + + fun isCustom(): Boolean = custom != null + + fun isApplyPatch(): Boolean = applyPatch != null + + fun isShell(): Boolean = shell != null + + /** + * Controls which (if any) tool is called by the model. + * + * `none` means the model will not call any tool and instead generates a message. + * + * `auto` means the model can pick between generating a message or calling one or more + * tools. + * + * `required` means the model must call one or more tools. + */ + fun asOptions(): ToolChoiceOptions = options.getOrThrow("options") + + /** Constrains the tools available to the model to a pre-defined set. */ + fun asAllowed(): ToolChoiceAllowed = allowed.getOrThrow("allowed") + + /** + * Indicates that the model should use a built-in tool to generate a response. + * [Learn more about built-in tools](https://platform.openai.com/docs/guides/tools). + */ + fun asTypes(): ToolChoiceTypes = types.getOrThrow("types") + + /** Use this option to force the model to call a specific function. */ + fun asFunction(): ToolChoiceFunction = function.getOrThrow("function") + + /** Use this option to force the model to call a specific tool on a remote MCP server. */ + fun asMcp(): ToolChoiceMcp = mcp.getOrThrow("mcp") + + /** Use this option to force the model to call a specific custom tool. */ + fun asCustom(): ToolChoiceCustom = custom.getOrThrow("custom") + + /** Forces the model to call the apply_patch tool when executing a tool call. */ + fun asApplyPatch(): ToolChoiceApplyPatch = applyPatch.getOrThrow("applyPatch") + + /** Forces the model to call the shell tool when a tool call is required. */ + fun asShell(): ToolChoiceShell = shell.getOrThrow("shell") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + options != null -> visitor.visitOptions(options) + allowed != null -> visitor.visitAllowed(allowed) + types != null -> visitor.visitTypes(types) + function != null -> visitor.visitFunction(function) + mcp != null -> visitor.visitMcp(mcp) + custom != null -> visitor.visitCustom(custom) + applyPatch != null -> visitor.visitApplyPatch(applyPatch) + shell != null -> visitor.visitShell(shell) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): ToolChoice = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitOptions(options: ToolChoiceOptions) { + options.validate() + } + + override fun visitAllowed(allowed: ToolChoiceAllowed) { + allowed.validate() + } + + override fun visitTypes(types: ToolChoiceTypes) { + types.validate() + } + + override fun visitFunction(function: ToolChoiceFunction) { + function.validate() + } + + override fun visitMcp(mcp: ToolChoiceMcp) { + mcp.validate() + } + + override fun visitCustom(custom: ToolChoiceCustom) { + custom.validate() + } + + override fun visitApplyPatch(applyPatch: ToolChoiceApplyPatch) { + applyPatch.validate() + } + + override fun visitShell(shell: ToolChoiceShell) { + shell.validate() + } + } + ) + 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 = + accept( + object : Visitor { + override fun visitOptions(options: ToolChoiceOptions) = options.validity() + + override fun visitAllowed(allowed: ToolChoiceAllowed) = allowed.validity() + + override fun visitTypes(types: ToolChoiceTypes) = types.validity() + + override fun visitFunction(function: ToolChoiceFunction) = function.validity() + + override fun visitMcp(mcp: ToolChoiceMcp) = mcp.validity() + + override fun visitCustom(custom: ToolChoiceCustom) = custom.validity() + + override fun visitApplyPatch(applyPatch: ToolChoiceApplyPatch) = + applyPatch.validity() + + override fun visitShell(shell: ToolChoiceShell) = shell.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ToolChoice && + options == other.options && + allowed == other.allowed && + types == other.types && + function == other.function && + mcp == other.mcp && + custom == other.custom && + applyPatch == other.applyPatch && + shell == other.shell + } + + override fun hashCode(): Int = + Objects.hash(options, allowed, types, function, mcp, custom, applyPatch, shell) + + override fun toString(): String = + when { + options != null -> "ToolChoice{options=$options}" + allowed != null -> "ToolChoice{allowed=$allowed}" + types != null -> "ToolChoice{types=$types}" + function != null -> "ToolChoice{function=$function}" + mcp != null -> "ToolChoice{mcp=$mcp}" + custom != null -> "ToolChoice{custom=$custom}" + applyPatch != null -> "ToolChoice{applyPatch=$applyPatch}" + shell != null -> "ToolChoice{shell=$shell}" + _json != null -> "ToolChoice{_unknown=$_json}" + else -> throw IllegalStateException("Invalid ToolChoice") + } + + companion object { + + /** + * Controls which (if any) tool is called by the model. + * + * `none` means the model will not call any tool and instead generates a message. + * + * `auto` means the model can pick between generating a message or calling one or more + * tools. + * + * `required` means the model must call one or more tools. + */ + @JvmStatic fun ofOptions(options: ToolChoiceOptions) = ToolChoice(options = options) + + /** Constrains the tools available to the model to a pre-defined set. */ + @JvmStatic fun ofAllowed(allowed: ToolChoiceAllowed) = ToolChoice(allowed = allowed) + + /** + * Indicates that the model should use a built-in tool to generate a response. + * [Learn more about built-in tools](https://platform.openai.com/docs/guides/tools). + */ + @JvmStatic fun ofTypes(types: ToolChoiceTypes) = ToolChoice(types = types) + + /** Use this option to force the model to call a specific function. */ + @JvmStatic + fun ofFunction(function: ToolChoiceFunction) = ToolChoice(function = function) + + /** + * Use this option to force the model to call a specific tool on a remote MCP server. + */ + @JvmStatic fun ofMcp(mcp: ToolChoiceMcp) = ToolChoice(mcp = mcp) + + /** Use this option to force the model to call a specific custom tool. */ + @JvmStatic fun ofCustom(custom: ToolChoiceCustom) = ToolChoice(custom = custom) + + /** Forces the model to call the apply_patch tool when executing a tool call. */ + @JvmStatic + fun ofApplyPatch(applyPatch: ToolChoiceApplyPatch) = ToolChoice(applyPatch = applyPatch) + + /** Forces the model to call the shell tool when a tool call is required. */ + @JvmStatic fun ofShell(shell: ToolChoiceShell) = ToolChoice(shell = shell) + } + + /** + * An interface that defines how to map each variant of [ToolChoice] to a value of type [T]. + */ + interface Visitor { + + /** + * Controls which (if any) tool is called by the model. + * + * `none` means the model will not call any tool and instead generates a message. + * + * `auto` means the model can pick between generating a message or calling one or more + * tools. + * + * `required` means the model must call one or more tools. + */ + fun visitOptions(options: ToolChoiceOptions): T + + /** Constrains the tools available to the model to a pre-defined set. */ + fun visitAllowed(allowed: ToolChoiceAllowed): T + + /** + * Indicates that the model should use a built-in tool to generate a response. + * [Learn more about built-in tools](https://platform.openai.com/docs/guides/tools). + */ + fun visitTypes(types: ToolChoiceTypes): T + + /** Use this option to force the model to call a specific function. */ + fun visitFunction(function: ToolChoiceFunction): T + + /** + * Use this option to force the model to call a specific tool on a remote MCP server. + */ + fun visitMcp(mcp: ToolChoiceMcp): T + + /** Use this option to force the model to call a specific custom tool. */ + fun visitCustom(custom: ToolChoiceCustom): T + + /** Forces the model to call the apply_patch tool when executing a tool call. */ + fun visitApplyPatch(applyPatch: ToolChoiceApplyPatch): T + + /** Forces the model to call the shell tool when a tool call is required. */ + fun visitShell(shell: ToolChoiceShell): T + + /** + * Maps an unknown variant of [ToolChoice] to a value of type [T]. + * + * An instance of [ToolChoice] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the SDK + * is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown ToolChoice: $json") + } + } + + internal class Deserializer : BaseDeserializer(ToolChoice::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): ToolChoice { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + ToolChoice(options = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + ToolChoice(allowed = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + ToolChoice(types = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + ToolChoice(function = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + ToolChoice(mcp = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + ToolChoice(custom = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + ToolChoice(applyPatch = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + ToolChoice(shell = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from boolean). + 0 -> ToolChoice(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(ToolChoice::class) { + + override fun serialize( + value: ToolChoice, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.options != null -> generator.writeObject(value.options) + value.allowed != null -> generator.writeObject(value.allowed) + value.types != null -> generator.writeObject(value.types) + value.function != null -> generator.writeObject(value.function) + value.mcp != null -> generator.writeObject(value.mcp) + value.custom != null -> generator.writeObject(value.custom) + value.applyPatch != null -> generator.writeObject(value.applyPatch) + value.shell != null -> generator.writeObject(value.shell) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid ToolChoice") + } + } + } + } + + /** + * The truncation strategy to use for the model response. + * - `auto`: If the input to this Response exceeds the model's context window size, the model + * will truncate the response to fit the context window by dropping items from the beginning + * of the conversation. + * - `disabled` (default): If the input size will exceed the context window size for a model, + * the request will fail with a 400 error. + */ + class Truncation @JsonCreator private constructor(private val value: JsonField) : 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 = value + + companion object { + + @JvmField val AUTO = of("auto") + + @JvmField val DISABLED = of("disabled") + + @JvmStatic fun of(value: String) = Truncation(JsonField.of(value)) + } + + /** An enum containing [Truncation]'s known values. */ + enum class Known { + AUTO, + DISABLED, + } + + /** + * An enum containing [Truncation]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Truncation] 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 { + AUTO, + DISABLED, + /** + * An enum member indicating that [Truncation] 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) { + AUTO -> Value.AUTO + DISABLED -> Value.DISABLED + 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) { + AUTO -> Known.AUTO + DISABLED -> Known.DISABLED + else -> throw OpenAIInvalidDataException("Unknown Truncation: $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(): Truncation = 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 Truncation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ResponsesClientEvent && + type == other.type && + background == other.background && + contextManagement == other.contextManagement && + conversation == other.conversation && + include == other.include && + input == other.input && + instructions == other.instructions && + maxOutputTokens == other.maxOutputTokens && + maxToolCalls == other.maxToolCalls && + metadata == other.metadata && + model == other.model && + parallelToolCalls == other.parallelToolCalls && + previousResponseId == other.previousResponseId && + prompt == other.prompt && + promptCacheKey == other.promptCacheKey && + promptCacheRetention == other.promptCacheRetention && + reasoning == other.reasoning && + safetyIdentifier == other.safetyIdentifier && + serviceTier == other.serviceTier && + store == other.store && + stream == other.stream && + streamOptions == other.streamOptions && + temperature == other.temperature && + text == other.text && + toolChoice == other.toolChoice && + tools == other.tools && + topLogprobs == other.topLogprobs && + topP == other.topP && + truncation == other.truncation && + user == other.user && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + type, + background, + contextManagement, + conversation, + include, + input, + instructions, + maxOutputTokens, + maxToolCalls, + metadata, + model, + parallelToolCalls, + previousResponseId, + prompt, + promptCacheKey, + promptCacheRetention, + reasoning, + safetyIdentifier, + serviceTier, + store, + stream, + streamOptions, + temperature, + text, + toolChoice, + tools, + topLogprobs, + topP, + truncation, + user, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ResponsesClientEvent{type=$type, 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, stream=$stream, streamOptions=$streamOptions, temperature=$temperature, text=$text, toolChoice=$toolChoice, tools=$tools, topLogprobs=$topLogprobs, topP=$topP, truncation=$truncation, user=$user, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponsesServerEvent.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponsesServerEvent.kt new file mode 100644 index 000000000..222e0560a --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponsesServerEvent.kt @@ -0,0 +1,2702 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.responses + +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer +import com.openai.core.JsonValue +import com.openai.core.getOrThrow +import com.openai.errors.OpenAIInvalidDataException +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Server events emitted by the Responses WebSocket server. */ +@JsonDeserialize(using = ResponsesServerEvent.Deserializer::class) +@JsonSerialize(using = ResponsesServerEvent.Serializer::class) +class ResponsesServerEvent +private constructor( + private val responseAudioDelta: ResponseAudioDeltaEvent? = null, + private val responseAudioDone: ResponseAudioDoneEvent? = null, + private val responseAudioTranscriptDelta: ResponseAudioTranscriptDeltaEvent? = null, + private val responseAudioTranscriptDone: ResponseAudioTranscriptDoneEvent? = null, + private val responseCodeInterpreterCallCodeDelta: ResponseCodeInterpreterCallCodeDeltaEvent? = + null, + private val responseCodeInterpreterCallCodeDone: ResponseCodeInterpreterCallCodeDoneEvent? = + null, + private val responseCodeInterpreterCallCompleted: ResponseCodeInterpreterCallCompletedEvent? = + null, + private val responseCodeInterpreterCallInProgress: ResponseCodeInterpreterCallInProgressEvent? = + null, + private val responseCodeInterpreterCallInterpreting: + ResponseCodeInterpreterCallInterpretingEvent? = + null, + private val responseCompleted: ResponseCompletedEvent? = null, + private val responseContentPartAdded: ResponseContentPartAddedEvent? = null, + private val responseContentPartDone: ResponseContentPartDoneEvent? = null, + private val responseCreated: ResponseCreatedEvent? = null, + private val error: ResponseErrorEvent? = null, + private val responseFileSearchCallCompleted: ResponseFileSearchCallCompletedEvent? = null, + private val responseFileSearchCallInProgress: ResponseFileSearchCallInProgressEvent? = null, + private val responseFileSearchCallSearching: ResponseFileSearchCallSearchingEvent? = null, + private val responseFunctionCallArgumentsDelta: ResponseFunctionCallArgumentsDeltaEvent? = null, + private val responseFunctionCallArgumentsDone: ResponseFunctionCallArgumentsDoneEvent? = null, + private val responseInProgress: ResponseInProgressEvent? = null, + private val responseFailed: ResponseFailedEvent? = null, + private val responseIncomplete: ResponseIncompleteEvent? = null, + private val responseOutputItemAdded: ResponseOutputItemAddedEvent? = null, + private val responseOutputItemDone: ResponseOutputItemDoneEvent? = null, + private val responseReasoningSummaryPartAdded: ResponseReasoningSummaryPartAddedEvent? = null, + private val responseReasoningSummaryPartDone: ResponseReasoningSummaryPartDoneEvent? = null, + private val responseReasoningSummaryTextDelta: ResponseReasoningSummaryTextDeltaEvent? = null, + private val responseReasoningSummaryTextDone: ResponseReasoningSummaryTextDoneEvent? = null, + private val responseReasoningTextDelta: ResponseReasoningTextDeltaEvent? = null, + private val responseReasoningTextDone: ResponseReasoningTextDoneEvent? = null, + private val responseRefusalDelta: ResponseRefusalDeltaEvent? = null, + private val responseRefusalDone: ResponseRefusalDoneEvent? = null, + private val responseOutputTextDelta: ResponseTextDeltaEvent? = null, + private val responseOutputTextDone: ResponseTextDoneEvent? = null, + private val responseWebSearchCallCompleted: ResponseWebSearchCallCompletedEvent? = null, + private val responseWebSearchCallInProgress: ResponseWebSearchCallInProgressEvent? = null, + private val responseWebSearchCallSearching: ResponseWebSearchCallSearchingEvent? = null, + private val responseImageGenerationCallCompleted: ResponseImageGenCallCompletedEvent? = null, + private val responseImageGenerationCallGenerating: ResponseImageGenCallGeneratingEvent? = null, + private val responseImageGenerationCallInProgress: ResponseImageGenCallInProgressEvent? = null, + private val responseImageGenerationCallPartialImage: ResponseImageGenCallPartialImageEvent? = + null, + private val responseMcpCallArgumentsDelta: ResponseMcpCallArgumentsDeltaEvent? = null, + private val responseMcpCallArgumentsDone: ResponseMcpCallArgumentsDoneEvent? = null, + private val responseMcpCallCompleted: ResponseMcpCallCompletedEvent? = null, + private val responseMcpCallFailed: ResponseMcpCallFailedEvent? = null, + private val responseMcpCallInProgress: ResponseMcpCallInProgressEvent? = null, + private val responseMcpListToolsCompleted: ResponseMcpListToolsCompletedEvent? = null, + private val responseMcpListToolsFailed: ResponseMcpListToolsFailedEvent? = null, + private val responseMcpListToolsInProgress: ResponseMcpListToolsInProgressEvent? = null, + private val responseOutputTextAnnotationAdded: ResponseOutputTextAnnotationAddedEvent? = null, + private val responseQueued: ResponseQueuedEvent? = null, + private val responseCustomToolCallInputDelta: ResponseCustomToolCallInputDeltaEvent? = null, + private val responseCustomToolCallInputDone: ResponseCustomToolCallInputDoneEvent? = null, + private val _json: JsonValue? = null, +) { + + /** Emitted when there is a partial audio response. */ + fun responseAudioDelta(): Optional = + Optional.ofNullable(responseAudioDelta) + + /** Emitted when the audio response is complete. */ + fun responseAudioDone(): Optional = + Optional.ofNullable(responseAudioDone) + + /** Emitted when there is a partial transcript of audio. */ + fun responseAudioTranscriptDelta(): Optional = + Optional.ofNullable(responseAudioTranscriptDelta) + + /** Emitted when the full audio transcript is completed. */ + fun responseAudioTranscriptDone(): Optional = + Optional.ofNullable(responseAudioTranscriptDone) + + /** Emitted when a partial code snippet is streamed by the code interpreter. */ + fun responseCodeInterpreterCallCodeDelta(): + Optional = + Optional.ofNullable(responseCodeInterpreterCallCodeDelta) + + /** Emitted when the code snippet is finalized by the code interpreter. */ + fun responseCodeInterpreterCallCodeDone(): Optional = + Optional.ofNullable(responseCodeInterpreterCallCodeDone) + + /** Emitted when the code interpreter call is completed. */ + fun responseCodeInterpreterCallCompleted(): + Optional = + Optional.ofNullable(responseCodeInterpreterCallCompleted) + + /** Emitted when a code interpreter call is in progress. */ + fun responseCodeInterpreterCallInProgress(): + Optional = + Optional.ofNullable(responseCodeInterpreterCallInProgress) + + /** Emitted when the code interpreter is actively interpreting the code snippet. */ + fun responseCodeInterpreterCallInterpreting(): + Optional = + Optional.ofNullable(responseCodeInterpreterCallInterpreting) + + /** Emitted when the model response is complete. */ + fun responseCompleted(): Optional = + Optional.ofNullable(responseCompleted) + + /** Emitted when a new content part is added. */ + fun responseContentPartAdded(): Optional = + Optional.ofNullable(responseContentPartAdded) + + /** Emitted when a content part is done. */ + fun responseContentPartDone(): Optional = + Optional.ofNullable(responseContentPartDone) + + /** An event that is emitted when a response is created. */ + fun responseCreated(): Optional = Optional.ofNullable(responseCreated) + + /** Emitted when an error occurs. */ + fun error(): Optional = Optional.ofNullable(error) + + /** Emitted when a file search call is completed (results found). */ + fun responseFileSearchCallCompleted(): Optional = + Optional.ofNullable(responseFileSearchCallCompleted) + + /** Emitted when a file search call is initiated. */ + fun responseFileSearchCallInProgress(): Optional = + Optional.ofNullable(responseFileSearchCallInProgress) + + /** Emitted when a file search is currently searching. */ + fun responseFileSearchCallSearching(): Optional = + Optional.ofNullable(responseFileSearchCallSearching) + + /** Emitted when there is a partial function-call arguments delta. */ + fun responseFunctionCallArgumentsDelta(): Optional = + Optional.ofNullable(responseFunctionCallArgumentsDelta) + + /** Emitted when function-call arguments are finalized. */ + fun responseFunctionCallArgumentsDone(): Optional = + Optional.ofNullable(responseFunctionCallArgumentsDone) + + /** Emitted when the response is in progress. */ + fun responseInProgress(): Optional = + Optional.ofNullable(responseInProgress) + + /** An event that is emitted when a response fails. */ + fun responseFailed(): Optional = Optional.ofNullable(responseFailed) + + /** An event that is emitted when a response finishes as incomplete. */ + fun responseIncomplete(): Optional = + Optional.ofNullable(responseIncomplete) + + /** Emitted when a new output item is added. */ + fun responseOutputItemAdded(): Optional = + Optional.ofNullable(responseOutputItemAdded) + + /** Emitted when an output item is marked done. */ + fun responseOutputItemDone(): Optional = + Optional.ofNullable(responseOutputItemDone) + + /** Emitted when a new reasoning summary part is added. */ + fun responseReasoningSummaryPartAdded(): Optional = + Optional.ofNullable(responseReasoningSummaryPartAdded) + + /** Emitted when a reasoning summary part is completed. */ + fun responseReasoningSummaryPartDone(): Optional = + Optional.ofNullable(responseReasoningSummaryPartDone) + + /** Emitted when a delta is added to a reasoning summary text. */ + fun responseReasoningSummaryTextDelta(): Optional = + Optional.ofNullable(responseReasoningSummaryTextDelta) + + /** Emitted when a reasoning summary text is completed. */ + fun responseReasoningSummaryTextDone(): Optional = + Optional.ofNullable(responseReasoningSummaryTextDone) + + /** Emitted when a delta is added to a reasoning text. */ + fun responseReasoningTextDelta(): Optional = + Optional.ofNullable(responseReasoningTextDelta) + + /** Emitted when a reasoning text is completed. */ + fun responseReasoningTextDone(): Optional = + Optional.ofNullable(responseReasoningTextDone) + + /** Emitted when there is a partial refusal text. */ + fun responseRefusalDelta(): Optional = + Optional.ofNullable(responseRefusalDelta) + + /** Emitted when refusal text is finalized. */ + fun responseRefusalDone(): Optional = + Optional.ofNullable(responseRefusalDone) + + /** Emitted when there is an additional text delta. */ + fun responseOutputTextDelta(): Optional = + Optional.ofNullable(responseOutputTextDelta) + + /** Emitted when text content is finalized. */ + fun responseOutputTextDone(): Optional = + Optional.ofNullable(responseOutputTextDone) + + /** Emitted when a web search call is completed. */ + fun responseWebSearchCallCompleted(): Optional = + Optional.ofNullable(responseWebSearchCallCompleted) + + /** Emitted when a web search call is initiated. */ + fun responseWebSearchCallInProgress(): Optional = + Optional.ofNullable(responseWebSearchCallInProgress) + + /** Emitted when a web search call is executing. */ + fun responseWebSearchCallSearching(): Optional = + Optional.ofNullable(responseWebSearchCallSearching) + + /** + * Emitted when an image generation tool call has completed and the final image is available. + */ + fun responseImageGenerationCallCompleted(): Optional = + Optional.ofNullable(responseImageGenerationCallCompleted) + + /** + * Emitted when an image generation tool call is actively generating an image (intermediate + * state). + */ + fun responseImageGenerationCallGenerating(): Optional = + Optional.ofNullable(responseImageGenerationCallGenerating) + + /** Emitted when an image generation tool call is in progress. */ + fun responseImageGenerationCallInProgress(): Optional = + Optional.ofNullable(responseImageGenerationCallInProgress) + + /** Emitted when a partial image is available during image generation streaming. */ + fun responseImageGenerationCallPartialImage(): Optional = + Optional.ofNullable(responseImageGenerationCallPartialImage) + + /** Emitted when there is a delta (partial update) to the arguments of an MCP tool call. */ + fun responseMcpCallArgumentsDelta(): Optional = + Optional.ofNullable(responseMcpCallArgumentsDelta) + + /** Emitted when the arguments for an MCP tool call are finalized. */ + fun responseMcpCallArgumentsDone(): Optional = + Optional.ofNullable(responseMcpCallArgumentsDone) + + /** Emitted when an MCP tool call has completed successfully. */ + fun responseMcpCallCompleted(): Optional = + Optional.ofNullable(responseMcpCallCompleted) + + /** Emitted when an MCP tool call has failed. */ + fun responseMcpCallFailed(): Optional = + Optional.ofNullable(responseMcpCallFailed) + + /** Emitted when an MCP tool call is in progress. */ + fun responseMcpCallInProgress(): Optional = + Optional.ofNullable(responseMcpCallInProgress) + + /** Emitted when the list of available MCP tools has been successfully retrieved. */ + fun responseMcpListToolsCompleted(): Optional = + Optional.ofNullable(responseMcpListToolsCompleted) + + /** Emitted when the attempt to list available MCP tools has failed. */ + fun responseMcpListToolsFailed(): Optional = + Optional.ofNullable(responseMcpListToolsFailed) + + /** Emitted when the system is in the process of retrieving the list of available MCP tools. */ + fun responseMcpListToolsInProgress(): Optional = + Optional.ofNullable(responseMcpListToolsInProgress) + + /** Emitted when an annotation is added to output text content. */ + fun responseOutputTextAnnotationAdded(): Optional = + Optional.ofNullable(responseOutputTextAnnotationAdded) + + /** Emitted when a response is queued and waiting to be processed. */ + fun responseQueued(): Optional = Optional.ofNullable(responseQueued) + + /** Event representing a delta (partial update) to the input of a custom tool call. */ + fun responseCustomToolCallInputDelta(): Optional = + Optional.ofNullable(responseCustomToolCallInputDelta) + + /** Event indicating that input for a custom tool call is complete. */ + fun responseCustomToolCallInputDone(): Optional = + Optional.ofNullable(responseCustomToolCallInputDone) + + fun isResponseAudioDelta(): Boolean = responseAudioDelta != null + + fun isResponseAudioDone(): Boolean = responseAudioDone != null + + fun isResponseAudioTranscriptDelta(): Boolean = responseAudioTranscriptDelta != null + + fun isResponseAudioTranscriptDone(): Boolean = responseAudioTranscriptDone != null + + fun isResponseCodeInterpreterCallCodeDelta(): Boolean = + responseCodeInterpreterCallCodeDelta != null + + fun isResponseCodeInterpreterCallCodeDone(): Boolean = + responseCodeInterpreterCallCodeDone != null + + fun isResponseCodeInterpreterCallCompleted(): Boolean = + responseCodeInterpreterCallCompleted != null + + fun isResponseCodeInterpreterCallInProgress(): Boolean = + responseCodeInterpreterCallInProgress != null + + fun isResponseCodeInterpreterCallInterpreting(): Boolean = + responseCodeInterpreterCallInterpreting != null + + fun isResponseCompleted(): Boolean = responseCompleted != null + + fun isResponseContentPartAdded(): Boolean = responseContentPartAdded != null + + fun isResponseContentPartDone(): Boolean = responseContentPartDone != null + + fun isResponseCreated(): Boolean = responseCreated != null + + fun isError(): Boolean = error != null + + fun isResponseFileSearchCallCompleted(): Boolean = responseFileSearchCallCompleted != null + + fun isResponseFileSearchCallInProgress(): Boolean = responseFileSearchCallInProgress != null + + fun isResponseFileSearchCallSearching(): Boolean = responseFileSearchCallSearching != null + + fun isResponseFunctionCallArgumentsDelta(): Boolean = responseFunctionCallArgumentsDelta != null + + fun isResponseFunctionCallArgumentsDone(): Boolean = responseFunctionCallArgumentsDone != null + + fun isResponseInProgress(): Boolean = responseInProgress != null + + fun isResponseFailed(): Boolean = responseFailed != null + + fun isResponseIncomplete(): Boolean = responseIncomplete != null + + fun isResponseOutputItemAdded(): Boolean = responseOutputItemAdded != null + + fun isResponseOutputItemDone(): Boolean = responseOutputItemDone != null + + fun isResponseReasoningSummaryPartAdded(): Boolean = responseReasoningSummaryPartAdded != null + + fun isResponseReasoningSummaryPartDone(): Boolean = responseReasoningSummaryPartDone != null + + fun isResponseReasoningSummaryTextDelta(): Boolean = responseReasoningSummaryTextDelta != null + + fun isResponseReasoningSummaryTextDone(): Boolean = responseReasoningSummaryTextDone != null + + fun isResponseReasoningTextDelta(): Boolean = responseReasoningTextDelta != null + + fun isResponseReasoningTextDone(): Boolean = responseReasoningTextDone != null + + fun isResponseRefusalDelta(): Boolean = responseRefusalDelta != null + + fun isResponseRefusalDone(): Boolean = responseRefusalDone != null + + fun isResponseOutputTextDelta(): Boolean = responseOutputTextDelta != null + + fun isResponseOutputTextDone(): Boolean = responseOutputTextDone != null + + fun isResponseWebSearchCallCompleted(): Boolean = responseWebSearchCallCompleted != null + + fun isResponseWebSearchCallInProgress(): Boolean = responseWebSearchCallInProgress != null + + fun isResponseWebSearchCallSearching(): Boolean = responseWebSearchCallSearching != null + + fun isResponseImageGenerationCallCompleted(): Boolean = + responseImageGenerationCallCompleted != null + + fun isResponseImageGenerationCallGenerating(): Boolean = + responseImageGenerationCallGenerating != null + + fun isResponseImageGenerationCallInProgress(): Boolean = + responseImageGenerationCallInProgress != null + + fun isResponseImageGenerationCallPartialImage(): Boolean = + responseImageGenerationCallPartialImage != null + + fun isResponseMcpCallArgumentsDelta(): Boolean = responseMcpCallArgumentsDelta != null + + fun isResponseMcpCallArgumentsDone(): Boolean = responseMcpCallArgumentsDone != null + + fun isResponseMcpCallCompleted(): Boolean = responseMcpCallCompleted != null + + fun isResponseMcpCallFailed(): Boolean = responseMcpCallFailed != null + + fun isResponseMcpCallInProgress(): Boolean = responseMcpCallInProgress != null + + fun isResponseMcpListToolsCompleted(): Boolean = responseMcpListToolsCompleted != null + + fun isResponseMcpListToolsFailed(): Boolean = responseMcpListToolsFailed != null + + fun isResponseMcpListToolsInProgress(): Boolean = responseMcpListToolsInProgress != null + + fun isResponseOutputTextAnnotationAdded(): Boolean = responseOutputTextAnnotationAdded != null + + fun isResponseQueued(): Boolean = responseQueued != null + + fun isResponseCustomToolCallInputDelta(): Boolean = responseCustomToolCallInputDelta != null + + fun isResponseCustomToolCallInputDone(): Boolean = responseCustomToolCallInputDone != null + + /** Emitted when there is a partial audio response. */ + fun asResponseAudioDelta(): ResponseAudioDeltaEvent = + responseAudioDelta.getOrThrow("responseAudioDelta") + + /** Emitted when the audio response is complete. */ + fun asResponseAudioDone(): ResponseAudioDoneEvent = + responseAudioDone.getOrThrow("responseAudioDone") + + /** Emitted when there is a partial transcript of audio. */ + fun asResponseAudioTranscriptDelta(): ResponseAudioTranscriptDeltaEvent = + responseAudioTranscriptDelta.getOrThrow("responseAudioTranscriptDelta") + + /** Emitted when the full audio transcript is completed. */ + fun asResponseAudioTranscriptDone(): ResponseAudioTranscriptDoneEvent = + responseAudioTranscriptDone.getOrThrow("responseAudioTranscriptDone") + + /** Emitted when a partial code snippet is streamed by the code interpreter. */ + fun asResponseCodeInterpreterCallCodeDelta(): ResponseCodeInterpreterCallCodeDeltaEvent = + responseCodeInterpreterCallCodeDelta.getOrThrow("responseCodeInterpreterCallCodeDelta") + + /** Emitted when the code snippet is finalized by the code interpreter. */ + fun asResponseCodeInterpreterCallCodeDone(): ResponseCodeInterpreterCallCodeDoneEvent = + responseCodeInterpreterCallCodeDone.getOrThrow("responseCodeInterpreterCallCodeDone") + + /** Emitted when the code interpreter call is completed. */ + fun asResponseCodeInterpreterCallCompleted(): ResponseCodeInterpreterCallCompletedEvent = + responseCodeInterpreterCallCompleted.getOrThrow("responseCodeInterpreterCallCompleted") + + /** Emitted when a code interpreter call is in progress. */ + fun asResponseCodeInterpreterCallInProgress(): ResponseCodeInterpreterCallInProgressEvent = + responseCodeInterpreterCallInProgress.getOrThrow("responseCodeInterpreterCallInProgress") + + /** Emitted when the code interpreter is actively interpreting the code snippet. */ + fun asResponseCodeInterpreterCallInterpreting(): ResponseCodeInterpreterCallInterpretingEvent = + responseCodeInterpreterCallInterpreting.getOrThrow( + "responseCodeInterpreterCallInterpreting" + ) + + /** Emitted when the model response is complete. */ + fun asResponseCompleted(): ResponseCompletedEvent = + responseCompleted.getOrThrow("responseCompleted") + + /** Emitted when a new content part is added. */ + fun asResponseContentPartAdded(): ResponseContentPartAddedEvent = + responseContentPartAdded.getOrThrow("responseContentPartAdded") + + /** Emitted when a content part is done. */ + fun asResponseContentPartDone(): ResponseContentPartDoneEvent = + responseContentPartDone.getOrThrow("responseContentPartDone") + + /** An event that is emitted when a response is created. */ + fun asResponseCreated(): ResponseCreatedEvent = responseCreated.getOrThrow("responseCreated") + + /** Emitted when an error occurs. */ + fun asError(): ResponseErrorEvent = error.getOrThrow("error") + + /** Emitted when a file search call is completed (results found). */ + fun asResponseFileSearchCallCompleted(): ResponseFileSearchCallCompletedEvent = + responseFileSearchCallCompleted.getOrThrow("responseFileSearchCallCompleted") + + /** Emitted when a file search call is initiated. */ + fun asResponseFileSearchCallInProgress(): ResponseFileSearchCallInProgressEvent = + responseFileSearchCallInProgress.getOrThrow("responseFileSearchCallInProgress") + + /** Emitted when a file search is currently searching. */ + fun asResponseFileSearchCallSearching(): ResponseFileSearchCallSearchingEvent = + responseFileSearchCallSearching.getOrThrow("responseFileSearchCallSearching") + + /** Emitted when there is a partial function-call arguments delta. */ + fun asResponseFunctionCallArgumentsDelta(): ResponseFunctionCallArgumentsDeltaEvent = + responseFunctionCallArgumentsDelta.getOrThrow("responseFunctionCallArgumentsDelta") + + /** Emitted when function-call arguments are finalized. */ + fun asResponseFunctionCallArgumentsDone(): ResponseFunctionCallArgumentsDoneEvent = + responseFunctionCallArgumentsDone.getOrThrow("responseFunctionCallArgumentsDone") + + /** Emitted when the response is in progress. */ + fun asResponseInProgress(): ResponseInProgressEvent = + responseInProgress.getOrThrow("responseInProgress") + + /** An event that is emitted when a response fails. */ + fun asResponseFailed(): ResponseFailedEvent = responseFailed.getOrThrow("responseFailed") + + /** An event that is emitted when a response finishes as incomplete. */ + fun asResponseIncomplete(): ResponseIncompleteEvent = + responseIncomplete.getOrThrow("responseIncomplete") + + /** Emitted when a new output item is added. */ + fun asResponseOutputItemAdded(): ResponseOutputItemAddedEvent = + responseOutputItemAdded.getOrThrow("responseOutputItemAdded") + + /** Emitted when an output item is marked done. */ + fun asResponseOutputItemDone(): ResponseOutputItemDoneEvent = + responseOutputItemDone.getOrThrow("responseOutputItemDone") + + /** Emitted when a new reasoning summary part is added. */ + fun asResponseReasoningSummaryPartAdded(): ResponseReasoningSummaryPartAddedEvent = + responseReasoningSummaryPartAdded.getOrThrow("responseReasoningSummaryPartAdded") + + /** Emitted when a reasoning summary part is completed. */ + fun asResponseReasoningSummaryPartDone(): ResponseReasoningSummaryPartDoneEvent = + responseReasoningSummaryPartDone.getOrThrow("responseReasoningSummaryPartDone") + + /** Emitted when a delta is added to a reasoning summary text. */ + fun asResponseReasoningSummaryTextDelta(): ResponseReasoningSummaryTextDeltaEvent = + responseReasoningSummaryTextDelta.getOrThrow("responseReasoningSummaryTextDelta") + + /** Emitted when a reasoning summary text is completed. */ + fun asResponseReasoningSummaryTextDone(): ResponseReasoningSummaryTextDoneEvent = + responseReasoningSummaryTextDone.getOrThrow("responseReasoningSummaryTextDone") + + /** Emitted when a delta is added to a reasoning text. */ + fun asResponseReasoningTextDelta(): ResponseReasoningTextDeltaEvent = + responseReasoningTextDelta.getOrThrow("responseReasoningTextDelta") + + /** Emitted when a reasoning text is completed. */ + fun asResponseReasoningTextDone(): ResponseReasoningTextDoneEvent = + responseReasoningTextDone.getOrThrow("responseReasoningTextDone") + + /** Emitted when there is a partial refusal text. */ + fun asResponseRefusalDelta(): ResponseRefusalDeltaEvent = + responseRefusalDelta.getOrThrow("responseRefusalDelta") + + /** Emitted when refusal text is finalized. */ + fun asResponseRefusalDone(): ResponseRefusalDoneEvent = + responseRefusalDone.getOrThrow("responseRefusalDone") + + /** Emitted when there is an additional text delta. */ + fun asResponseOutputTextDelta(): ResponseTextDeltaEvent = + responseOutputTextDelta.getOrThrow("responseOutputTextDelta") + + /** Emitted when text content is finalized. */ + fun asResponseOutputTextDone(): ResponseTextDoneEvent = + responseOutputTextDone.getOrThrow("responseOutputTextDone") + + /** Emitted when a web search call is completed. */ + fun asResponseWebSearchCallCompleted(): ResponseWebSearchCallCompletedEvent = + responseWebSearchCallCompleted.getOrThrow("responseWebSearchCallCompleted") + + /** Emitted when a web search call is initiated. */ + fun asResponseWebSearchCallInProgress(): ResponseWebSearchCallInProgressEvent = + responseWebSearchCallInProgress.getOrThrow("responseWebSearchCallInProgress") + + /** Emitted when a web search call is executing. */ + fun asResponseWebSearchCallSearching(): ResponseWebSearchCallSearchingEvent = + responseWebSearchCallSearching.getOrThrow("responseWebSearchCallSearching") + + /** + * Emitted when an image generation tool call has completed and the final image is available. + */ + fun asResponseImageGenerationCallCompleted(): ResponseImageGenCallCompletedEvent = + responseImageGenerationCallCompleted.getOrThrow("responseImageGenerationCallCompleted") + + /** + * Emitted when an image generation tool call is actively generating an image (intermediate + * state). + */ + fun asResponseImageGenerationCallGenerating(): ResponseImageGenCallGeneratingEvent = + responseImageGenerationCallGenerating.getOrThrow("responseImageGenerationCallGenerating") + + /** Emitted when an image generation tool call is in progress. */ + fun asResponseImageGenerationCallInProgress(): ResponseImageGenCallInProgressEvent = + responseImageGenerationCallInProgress.getOrThrow("responseImageGenerationCallInProgress") + + /** Emitted when a partial image is available during image generation streaming. */ + fun asResponseImageGenerationCallPartialImage(): ResponseImageGenCallPartialImageEvent = + responseImageGenerationCallPartialImage.getOrThrow( + "responseImageGenerationCallPartialImage" + ) + + /** Emitted when there is a delta (partial update) to the arguments of an MCP tool call. */ + fun asResponseMcpCallArgumentsDelta(): ResponseMcpCallArgumentsDeltaEvent = + responseMcpCallArgumentsDelta.getOrThrow("responseMcpCallArgumentsDelta") + + /** Emitted when the arguments for an MCP tool call are finalized. */ + fun asResponseMcpCallArgumentsDone(): ResponseMcpCallArgumentsDoneEvent = + responseMcpCallArgumentsDone.getOrThrow("responseMcpCallArgumentsDone") + + /** Emitted when an MCP tool call has completed successfully. */ + fun asResponseMcpCallCompleted(): ResponseMcpCallCompletedEvent = + responseMcpCallCompleted.getOrThrow("responseMcpCallCompleted") + + /** Emitted when an MCP tool call has failed. */ + fun asResponseMcpCallFailed(): ResponseMcpCallFailedEvent = + responseMcpCallFailed.getOrThrow("responseMcpCallFailed") + + /** Emitted when an MCP tool call is in progress. */ + fun asResponseMcpCallInProgress(): ResponseMcpCallInProgressEvent = + responseMcpCallInProgress.getOrThrow("responseMcpCallInProgress") + + /** Emitted when the list of available MCP tools has been successfully retrieved. */ + fun asResponseMcpListToolsCompleted(): ResponseMcpListToolsCompletedEvent = + responseMcpListToolsCompleted.getOrThrow("responseMcpListToolsCompleted") + + /** Emitted when the attempt to list available MCP tools has failed. */ + fun asResponseMcpListToolsFailed(): ResponseMcpListToolsFailedEvent = + responseMcpListToolsFailed.getOrThrow("responseMcpListToolsFailed") + + /** Emitted when the system is in the process of retrieving the list of available MCP tools. */ + fun asResponseMcpListToolsInProgress(): ResponseMcpListToolsInProgressEvent = + responseMcpListToolsInProgress.getOrThrow("responseMcpListToolsInProgress") + + /** Emitted when an annotation is added to output text content. */ + fun asResponseOutputTextAnnotationAdded(): ResponseOutputTextAnnotationAddedEvent = + responseOutputTextAnnotationAdded.getOrThrow("responseOutputTextAnnotationAdded") + + /** Emitted when a response is queued and waiting to be processed. */ + fun asResponseQueued(): ResponseQueuedEvent = responseQueued.getOrThrow("responseQueued") + + /** Event representing a delta (partial update) to the input of a custom tool call. */ + fun asResponseCustomToolCallInputDelta(): ResponseCustomToolCallInputDeltaEvent = + responseCustomToolCallInputDelta.getOrThrow("responseCustomToolCallInputDelta") + + /** Event indicating that input for a custom tool call is complete. */ + fun asResponseCustomToolCallInputDone(): ResponseCustomToolCallInputDoneEvent = + responseCustomToolCallInputDone.getOrThrow("responseCustomToolCallInputDone") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + responseAudioDelta != null -> visitor.visitResponseAudioDelta(responseAudioDelta) + responseAudioDone != null -> visitor.visitResponseAudioDone(responseAudioDone) + responseAudioTranscriptDelta != null -> + visitor.visitResponseAudioTranscriptDelta(responseAudioTranscriptDelta) + responseAudioTranscriptDone != null -> + visitor.visitResponseAudioTranscriptDone(responseAudioTranscriptDone) + responseCodeInterpreterCallCodeDelta != null -> + visitor.visitResponseCodeInterpreterCallCodeDelta( + responseCodeInterpreterCallCodeDelta + ) + responseCodeInterpreterCallCodeDone != null -> + visitor.visitResponseCodeInterpreterCallCodeDone( + responseCodeInterpreterCallCodeDone + ) + responseCodeInterpreterCallCompleted != null -> + visitor.visitResponseCodeInterpreterCallCompleted( + responseCodeInterpreterCallCompleted + ) + responseCodeInterpreterCallInProgress != null -> + visitor.visitResponseCodeInterpreterCallInProgress( + responseCodeInterpreterCallInProgress + ) + responseCodeInterpreterCallInterpreting != null -> + visitor.visitResponseCodeInterpreterCallInterpreting( + responseCodeInterpreterCallInterpreting + ) + responseCompleted != null -> visitor.visitResponseCompleted(responseCompleted) + responseContentPartAdded != null -> + visitor.visitResponseContentPartAdded(responseContentPartAdded) + responseContentPartDone != null -> + visitor.visitResponseContentPartDone(responseContentPartDone) + responseCreated != null -> visitor.visitResponseCreated(responseCreated) + error != null -> visitor.visitError(error) + responseFileSearchCallCompleted != null -> + visitor.visitResponseFileSearchCallCompleted(responseFileSearchCallCompleted) + responseFileSearchCallInProgress != null -> + visitor.visitResponseFileSearchCallInProgress(responseFileSearchCallInProgress) + responseFileSearchCallSearching != null -> + visitor.visitResponseFileSearchCallSearching(responseFileSearchCallSearching) + responseFunctionCallArgumentsDelta != null -> + visitor.visitResponseFunctionCallArgumentsDelta(responseFunctionCallArgumentsDelta) + responseFunctionCallArgumentsDone != null -> + visitor.visitResponseFunctionCallArgumentsDone(responseFunctionCallArgumentsDone) + responseInProgress != null -> visitor.visitResponseInProgress(responseInProgress) + responseFailed != null -> visitor.visitResponseFailed(responseFailed) + responseIncomplete != null -> visitor.visitResponseIncomplete(responseIncomplete) + responseOutputItemAdded != null -> + visitor.visitResponseOutputItemAdded(responseOutputItemAdded) + responseOutputItemDone != null -> + visitor.visitResponseOutputItemDone(responseOutputItemDone) + responseReasoningSummaryPartAdded != null -> + visitor.visitResponseReasoningSummaryPartAdded(responseReasoningSummaryPartAdded) + responseReasoningSummaryPartDone != null -> + visitor.visitResponseReasoningSummaryPartDone(responseReasoningSummaryPartDone) + responseReasoningSummaryTextDelta != null -> + visitor.visitResponseReasoningSummaryTextDelta(responseReasoningSummaryTextDelta) + responseReasoningSummaryTextDone != null -> + visitor.visitResponseReasoningSummaryTextDone(responseReasoningSummaryTextDone) + responseReasoningTextDelta != null -> + visitor.visitResponseReasoningTextDelta(responseReasoningTextDelta) + responseReasoningTextDone != null -> + visitor.visitResponseReasoningTextDone(responseReasoningTextDone) + responseRefusalDelta != null -> visitor.visitResponseRefusalDelta(responseRefusalDelta) + responseRefusalDone != null -> visitor.visitResponseRefusalDone(responseRefusalDone) + responseOutputTextDelta != null -> + visitor.visitResponseOutputTextDelta(responseOutputTextDelta) + responseOutputTextDone != null -> + visitor.visitResponseOutputTextDone(responseOutputTextDone) + responseWebSearchCallCompleted != null -> + visitor.visitResponseWebSearchCallCompleted(responseWebSearchCallCompleted) + responseWebSearchCallInProgress != null -> + visitor.visitResponseWebSearchCallInProgress(responseWebSearchCallInProgress) + responseWebSearchCallSearching != null -> + visitor.visitResponseWebSearchCallSearching(responseWebSearchCallSearching) + responseImageGenerationCallCompleted != null -> + visitor.visitResponseImageGenerationCallCompleted( + responseImageGenerationCallCompleted + ) + responseImageGenerationCallGenerating != null -> + visitor.visitResponseImageGenerationCallGenerating( + responseImageGenerationCallGenerating + ) + responseImageGenerationCallInProgress != null -> + visitor.visitResponseImageGenerationCallInProgress( + responseImageGenerationCallInProgress + ) + responseImageGenerationCallPartialImage != null -> + visitor.visitResponseImageGenerationCallPartialImage( + responseImageGenerationCallPartialImage + ) + responseMcpCallArgumentsDelta != null -> + visitor.visitResponseMcpCallArgumentsDelta(responseMcpCallArgumentsDelta) + responseMcpCallArgumentsDone != null -> + visitor.visitResponseMcpCallArgumentsDone(responseMcpCallArgumentsDone) + responseMcpCallCompleted != null -> + visitor.visitResponseMcpCallCompleted(responseMcpCallCompleted) + responseMcpCallFailed != null -> + visitor.visitResponseMcpCallFailed(responseMcpCallFailed) + responseMcpCallInProgress != null -> + visitor.visitResponseMcpCallInProgress(responseMcpCallInProgress) + responseMcpListToolsCompleted != null -> + visitor.visitResponseMcpListToolsCompleted(responseMcpListToolsCompleted) + responseMcpListToolsFailed != null -> + visitor.visitResponseMcpListToolsFailed(responseMcpListToolsFailed) + responseMcpListToolsInProgress != null -> + visitor.visitResponseMcpListToolsInProgress(responseMcpListToolsInProgress) + responseOutputTextAnnotationAdded != null -> + visitor.visitResponseOutputTextAnnotationAdded(responseOutputTextAnnotationAdded) + responseQueued != null -> visitor.visitResponseQueued(responseQueued) + responseCustomToolCallInputDelta != null -> + visitor.visitResponseCustomToolCallInputDelta(responseCustomToolCallInputDelta) + responseCustomToolCallInputDone != null -> + visitor.visitResponseCustomToolCallInputDone(responseCustomToolCallInputDone) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): ResponsesServerEvent = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitResponseAudioDelta(responseAudioDelta: ResponseAudioDeltaEvent) { + responseAudioDelta.validate() + } + + override fun visitResponseAudioDone(responseAudioDone: ResponseAudioDoneEvent) { + responseAudioDone.validate() + } + + override fun visitResponseAudioTranscriptDelta( + responseAudioTranscriptDelta: ResponseAudioTranscriptDeltaEvent + ) { + responseAudioTranscriptDelta.validate() + } + + override fun visitResponseAudioTranscriptDone( + responseAudioTranscriptDone: ResponseAudioTranscriptDoneEvent + ) { + responseAudioTranscriptDone.validate() + } + + override fun visitResponseCodeInterpreterCallCodeDelta( + responseCodeInterpreterCallCodeDelta: ResponseCodeInterpreterCallCodeDeltaEvent + ) { + responseCodeInterpreterCallCodeDelta.validate() + } + + override fun visitResponseCodeInterpreterCallCodeDone( + responseCodeInterpreterCallCodeDone: ResponseCodeInterpreterCallCodeDoneEvent + ) { + responseCodeInterpreterCallCodeDone.validate() + } + + override fun visitResponseCodeInterpreterCallCompleted( + responseCodeInterpreterCallCompleted: ResponseCodeInterpreterCallCompletedEvent + ) { + responseCodeInterpreterCallCompleted.validate() + } + + override fun visitResponseCodeInterpreterCallInProgress( + responseCodeInterpreterCallInProgress: + ResponseCodeInterpreterCallInProgressEvent + ) { + responseCodeInterpreterCallInProgress.validate() + } + + override fun visitResponseCodeInterpreterCallInterpreting( + responseCodeInterpreterCallInterpreting: + ResponseCodeInterpreterCallInterpretingEvent + ) { + responseCodeInterpreterCallInterpreting.validate() + } + + override fun visitResponseCompleted(responseCompleted: ResponseCompletedEvent) { + responseCompleted.validate() + } + + override fun visitResponseContentPartAdded( + responseContentPartAdded: ResponseContentPartAddedEvent + ) { + responseContentPartAdded.validate() + } + + override fun visitResponseContentPartDone( + responseContentPartDone: ResponseContentPartDoneEvent + ) { + responseContentPartDone.validate() + } + + override fun visitResponseCreated(responseCreated: ResponseCreatedEvent) { + responseCreated.validate() + } + + override fun visitError(error: ResponseErrorEvent) { + error.validate() + } + + override fun visitResponseFileSearchCallCompleted( + responseFileSearchCallCompleted: ResponseFileSearchCallCompletedEvent + ) { + responseFileSearchCallCompleted.validate() + } + + override fun visitResponseFileSearchCallInProgress( + responseFileSearchCallInProgress: ResponseFileSearchCallInProgressEvent + ) { + responseFileSearchCallInProgress.validate() + } + + override fun visitResponseFileSearchCallSearching( + responseFileSearchCallSearching: ResponseFileSearchCallSearchingEvent + ) { + responseFileSearchCallSearching.validate() + } + + override fun visitResponseFunctionCallArgumentsDelta( + responseFunctionCallArgumentsDelta: ResponseFunctionCallArgumentsDeltaEvent + ) { + responseFunctionCallArgumentsDelta.validate() + } + + override fun visitResponseFunctionCallArgumentsDone( + responseFunctionCallArgumentsDone: ResponseFunctionCallArgumentsDoneEvent + ) { + responseFunctionCallArgumentsDone.validate() + } + + override fun visitResponseInProgress(responseInProgress: ResponseInProgressEvent) { + responseInProgress.validate() + } + + override fun visitResponseFailed(responseFailed: ResponseFailedEvent) { + responseFailed.validate() + } + + override fun visitResponseIncomplete(responseIncomplete: ResponseIncompleteEvent) { + responseIncomplete.validate() + } + + override fun visitResponseOutputItemAdded( + responseOutputItemAdded: ResponseOutputItemAddedEvent + ) { + responseOutputItemAdded.validate() + } + + override fun visitResponseOutputItemDone( + responseOutputItemDone: ResponseOutputItemDoneEvent + ) { + responseOutputItemDone.validate() + } + + override fun visitResponseReasoningSummaryPartAdded( + responseReasoningSummaryPartAdded: ResponseReasoningSummaryPartAddedEvent + ) { + responseReasoningSummaryPartAdded.validate() + } + + override fun visitResponseReasoningSummaryPartDone( + responseReasoningSummaryPartDone: ResponseReasoningSummaryPartDoneEvent + ) { + responseReasoningSummaryPartDone.validate() + } + + override fun visitResponseReasoningSummaryTextDelta( + responseReasoningSummaryTextDelta: ResponseReasoningSummaryTextDeltaEvent + ) { + responseReasoningSummaryTextDelta.validate() + } + + override fun visitResponseReasoningSummaryTextDone( + responseReasoningSummaryTextDone: ResponseReasoningSummaryTextDoneEvent + ) { + responseReasoningSummaryTextDone.validate() + } + + override fun visitResponseReasoningTextDelta( + responseReasoningTextDelta: ResponseReasoningTextDeltaEvent + ) { + responseReasoningTextDelta.validate() + } + + override fun visitResponseReasoningTextDone( + responseReasoningTextDone: ResponseReasoningTextDoneEvent + ) { + responseReasoningTextDone.validate() + } + + override fun visitResponseRefusalDelta( + responseRefusalDelta: ResponseRefusalDeltaEvent + ) { + responseRefusalDelta.validate() + } + + override fun visitResponseRefusalDone( + responseRefusalDone: ResponseRefusalDoneEvent + ) { + responseRefusalDone.validate() + } + + override fun visitResponseOutputTextDelta( + responseOutputTextDelta: ResponseTextDeltaEvent + ) { + responseOutputTextDelta.validate() + } + + override fun visitResponseOutputTextDone( + responseOutputTextDone: ResponseTextDoneEvent + ) { + responseOutputTextDone.validate() + } + + override fun visitResponseWebSearchCallCompleted( + responseWebSearchCallCompleted: ResponseWebSearchCallCompletedEvent + ) { + responseWebSearchCallCompleted.validate() + } + + override fun visitResponseWebSearchCallInProgress( + responseWebSearchCallInProgress: ResponseWebSearchCallInProgressEvent + ) { + responseWebSearchCallInProgress.validate() + } + + override fun visitResponseWebSearchCallSearching( + responseWebSearchCallSearching: ResponseWebSearchCallSearchingEvent + ) { + responseWebSearchCallSearching.validate() + } + + override fun visitResponseImageGenerationCallCompleted( + responseImageGenerationCallCompleted: ResponseImageGenCallCompletedEvent + ) { + responseImageGenerationCallCompleted.validate() + } + + override fun visitResponseImageGenerationCallGenerating( + responseImageGenerationCallGenerating: ResponseImageGenCallGeneratingEvent + ) { + responseImageGenerationCallGenerating.validate() + } + + override fun visitResponseImageGenerationCallInProgress( + responseImageGenerationCallInProgress: ResponseImageGenCallInProgressEvent + ) { + responseImageGenerationCallInProgress.validate() + } + + override fun visitResponseImageGenerationCallPartialImage( + responseImageGenerationCallPartialImage: ResponseImageGenCallPartialImageEvent + ) { + responseImageGenerationCallPartialImage.validate() + } + + override fun visitResponseMcpCallArgumentsDelta( + responseMcpCallArgumentsDelta: ResponseMcpCallArgumentsDeltaEvent + ) { + responseMcpCallArgumentsDelta.validate() + } + + override fun visitResponseMcpCallArgumentsDone( + responseMcpCallArgumentsDone: ResponseMcpCallArgumentsDoneEvent + ) { + responseMcpCallArgumentsDone.validate() + } + + override fun visitResponseMcpCallCompleted( + responseMcpCallCompleted: ResponseMcpCallCompletedEvent + ) { + responseMcpCallCompleted.validate() + } + + override fun visitResponseMcpCallFailed( + responseMcpCallFailed: ResponseMcpCallFailedEvent + ) { + responseMcpCallFailed.validate() + } + + override fun visitResponseMcpCallInProgress( + responseMcpCallInProgress: ResponseMcpCallInProgressEvent + ) { + responseMcpCallInProgress.validate() + } + + override fun visitResponseMcpListToolsCompleted( + responseMcpListToolsCompleted: ResponseMcpListToolsCompletedEvent + ) { + responseMcpListToolsCompleted.validate() + } + + override fun visitResponseMcpListToolsFailed( + responseMcpListToolsFailed: ResponseMcpListToolsFailedEvent + ) { + responseMcpListToolsFailed.validate() + } + + override fun visitResponseMcpListToolsInProgress( + responseMcpListToolsInProgress: ResponseMcpListToolsInProgressEvent + ) { + responseMcpListToolsInProgress.validate() + } + + override fun visitResponseOutputTextAnnotationAdded( + responseOutputTextAnnotationAdded: ResponseOutputTextAnnotationAddedEvent + ) { + responseOutputTextAnnotationAdded.validate() + } + + override fun visitResponseQueued(responseQueued: ResponseQueuedEvent) { + responseQueued.validate() + } + + override fun visitResponseCustomToolCallInputDelta( + responseCustomToolCallInputDelta: ResponseCustomToolCallInputDeltaEvent + ) { + responseCustomToolCallInputDelta.validate() + } + + override fun visitResponseCustomToolCallInputDone( + responseCustomToolCallInputDone: ResponseCustomToolCallInputDoneEvent + ) { + responseCustomToolCallInputDone.validate() + } + } + ) + 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 = + accept( + object : Visitor { + override fun visitResponseAudioDelta(responseAudioDelta: ResponseAudioDeltaEvent) = + responseAudioDelta.validity() + + override fun visitResponseAudioDone(responseAudioDone: ResponseAudioDoneEvent) = + responseAudioDone.validity() + + override fun visitResponseAudioTranscriptDelta( + responseAudioTranscriptDelta: ResponseAudioTranscriptDeltaEvent + ) = responseAudioTranscriptDelta.validity() + + override fun visitResponseAudioTranscriptDone( + responseAudioTranscriptDone: ResponseAudioTranscriptDoneEvent + ) = responseAudioTranscriptDone.validity() + + override fun visitResponseCodeInterpreterCallCodeDelta( + responseCodeInterpreterCallCodeDelta: ResponseCodeInterpreterCallCodeDeltaEvent + ) = responseCodeInterpreterCallCodeDelta.validity() + + override fun visitResponseCodeInterpreterCallCodeDone( + responseCodeInterpreterCallCodeDone: ResponseCodeInterpreterCallCodeDoneEvent + ) = responseCodeInterpreterCallCodeDone.validity() + + override fun visitResponseCodeInterpreterCallCompleted( + responseCodeInterpreterCallCompleted: ResponseCodeInterpreterCallCompletedEvent + ) = responseCodeInterpreterCallCompleted.validity() + + override fun visitResponseCodeInterpreterCallInProgress( + responseCodeInterpreterCallInProgress: + ResponseCodeInterpreterCallInProgressEvent + ) = responseCodeInterpreterCallInProgress.validity() + + override fun visitResponseCodeInterpreterCallInterpreting( + responseCodeInterpreterCallInterpreting: + ResponseCodeInterpreterCallInterpretingEvent + ) = responseCodeInterpreterCallInterpreting.validity() + + override fun visitResponseCompleted(responseCompleted: ResponseCompletedEvent) = + responseCompleted.validity() + + override fun visitResponseContentPartAdded( + responseContentPartAdded: ResponseContentPartAddedEvent + ) = responseContentPartAdded.validity() + + override fun visitResponseContentPartDone( + responseContentPartDone: ResponseContentPartDoneEvent + ) = responseContentPartDone.validity() + + override fun visitResponseCreated(responseCreated: ResponseCreatedEvent) = + responseCreated.validity() + + override fun visitError(error: ResponseErrorEvent) = error.validity() + + override fun visitResponseFileSearchCallCompleted( + responseFileSearchCallCompleted: ResponseFileSearchCallCompletedEvent + ) = responseFileSearchCallCompleted.validity() + + override fun visitResponseFileSearchCallInProgress( + responseFileSearchCallInProgress: ResponseFileSearchCallInProgressEvent + ) = responseFileSearchCallInProgress.validity() + + override fun visitResponseFileSearchCallSearching( + responseFileSearchCallSearching: ResponseFileSearchCallSearchingEvent + ) = responseFileSearchCallSearching.validity() + + override fun visitResponseFunctionCallArgumentsDelta( + responseFunctionCallArgumentsDelta: ResponseFunctionCallArgumentsDeltaEvent + ) = responseFunctionCallArgumentsDelta.validity() + + override fun visitResponseFunctionCallArgumentsDone( + responseFunctionCallArgumentsDone: ResponseFunctionCallArgumentsDoneEvent + ) = responseFunctionCallArgumentsDone.validity() + + override fun visitResponseInProgress(responseInProgress: ResponseInProgressEvent) = + responseInProgress.validity() + + override fun visitResponseFailed(responseFailed: ResponseFailedEvent) = + responseFailed.validity() + + override fun visitResponseIncomplete(responseIncomplete: ResponseIncompleteEvent) = + responseIncomplete.validity() + + override fun visitResponseOutputItemAdded( + responseOutputItemAdded: ResponseOutputItemAddedEvent + ) = responseOutputItemAdded.validity() + + override fun visitResponseOutputItemDone( + responseOutputItemDone: ResponseOutputItemDoneEvent + ) = responseOutputItemDone.validity() + + override fun visitResponseReasoningSummaryPartAdded( + responseReasoningSummaryPartAdded: ResponseReasoningSummaryPartAddedEvent + ) = responseReasoningSummaryPartAdded.validity() + + override fun visitResponseReasoningSummaryPartDone( + responseReasoningSummaryPartDone: ResponseReasoningSummaryPartDoneEvent + ) = responseReasoningSummaryPartDone.validity() + + override fun visitResponseReasoningSummaryTextDelta( + responseReasoningSummaryTextDelta: ResponseReasoningSummaryTextDeltaEvent + ) = responseReasoningSummaryTextDelta.validity() + + override fun visitResponseReasoningSummaryTextDone( + responseReasoningSummaryTextDone: ResponseReasoningSummaryTextDoneEvent + ) = responseReasoningSummaryTextDone.validity() + + override fun visitResponseReasoningTextDelta( + responseReasoningTextDelta: ResponseReasoningTextDeltaEvent + ) = responseReasoningTextDelta.validity() + + override fun visitResponseReasoningTextDone( + responseReasoningTextDone: ResponseReasoningTextDoneEvent + ) = responseReasoningTextDone.validity() + + override fun visitResponseRefusalDelta( + responseRefusalDelta: ResponseRefusalDeltaEvent + ) = responseRefusalDelta.validity() + + override fun visitResponseRefusalDone( + responseRefusalDone: ResponseRefusalDoneEvent + ) = responseRefusalDone.validity() + + override fun visitResponseOutputTextDelta( + responseOutputTextDelta: ResponseTextDeltaEvent + ) = responseOutputTextDelta.validity() + + override fun visitResponseOutputTextDone( + responseOutputTextDone: ResponseTextDoneEvent + ) = responseOutputTextDone.validity() + + override fun visitResponseWebSearchCallCompleted( + responseWebSearchCallCompleted: ResponseWebSearchCallCompletedEvent + ) = responseWebSearchCallCompleted.validity() + + override fun visitResponseWebSearchCallInProgress( + responseWebSearchCallInProgress: ResponseWebSearchCallInProgressEvent + ) = responseWebSearchCallInProgress.validity() + + override fun visitResponseWebSearchCallSearching( + responseWebSearchCallSearching: ResponseWebSearchCallSearchingEvent + ) = responseWebSearchCallSearching.validity() + + override fun visitResponseImageGenerationCallCompleted( + responseImageGenerationCallCompleted: ResponseImageGenCallCompletedEvent + ) = responseImageGenerationCallCompleted.validity() + + override fun visitResponseImageGenerationCallGenerating( + responseImageGenerationCallGenerating: ResponseImageGenCallGeneratingEvent + ) = responseImageGenerationCallGenerating.validity() + + override fun visitResponseImageGenerationCallInProgress( + responseImageGenerationCallInProgress: ResponseImageGenCallInProgressEvent + ) = responseImageGenerationCallInProgress.validity() + + override fun visitResponseImageGenerationCallPartialImage( + responseImageGenerationCallPartialImage: ResponseImageGenCallPartialImageEvent + ) = responseImageGenerationCallPartialImage.validity() + + override fun visitResponseMcpCallArgumentsDelta( + responseMcpCallArgumentsDelta: ResponseMcpCallArgumentsDeltaEvent + ) = responseMcpCallArgumentsDelta.validity() + + override fun visitResponseMcpCallArgumentsDone( + responseMcpCallArgumentsDone: ResponseMcpCallArgumentsDoneEvent + ) = responseMcpCallArgumentsDone.validity() + + override fun visitResponseMcpCallCompleted( + responseMcpCallCompleted: ResponseMcpCallCompletedEvent + ) = responseMcpCallCompleted.validity() + + override fun visitResponseMcpCallFailed( + responseMcpCallFailed: ResponseMcpCallFailedEvent + ) = responseMcpCallFailed.validity() + + override fun visitResponseMcpCallInProgress( + responseMcpCallInProgress: ResponseMcpCallInProgressEvent + ) = responseMcpCallInProgress.validity() + + override fun visitResponseMcpListToolsCompleted( + responseMcpListToolsCompleted: ResponseMcpListToolsCompletedEvent + ) = responseMcpListToolsCompleted.validity() + + override fun visitResponseMcpListToolsFailed( + responseMcpListToolsFailed: ResponseMcpListToolsFailedEvent + ) = responseMcpListToolsFailed.validity() + + override fun visitResponseMcpListToolsInProgress( + responseMcpListToolsInProgress: ResponseMcpListToolsInProgressEvent + ) = responseMcpListToolsInProgress.validity() + + override fun visitResponseOutputTextAnnotationAdded( + responseOutputTextAnnotationAdded: ResponseOutputTextAnnotationAddedEvent + ) = responseOutputTextAnnotationAdded.validity() + + override fun visitResponseQueued(responseQueued: ResponseQueuedEvent) = + responseQueued.validity() + + override fun visitResponseCustomToolCallInputDelta( + responseCustomToolCallInputDelta: ResponseCustomToolCallInputDeltaEvent + ) = responseCustomToolCallInputDelta.validity() + + override fun visitResponseCustomToolCallInputDone( + responseCustomToolCallInputDone: ResponseCustomToolCallInputDoneEvent + ) = responseCustomToolCallInputDone.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ResponsesServerEvent && + responseAudioDelta == other.responseAudioDelta && + responseAudioDone == other.responseAudioDone && + responseAudioTranscriptDelta == other.responseAudioTranscriptDelta && + responseAudioTranscriptDone == other.responseAudioTranscriptDone && + responseCodeInterpreterCallCodeDelta == other.responseCodeInterpreterCallCodeDelta && + responseCodeInterpreterCallCodeDone == other.responseCodeInterpreterCallCodeDone && + responseCodeInterpreterCallCompleted == other.responseCodeInterpreterCallCompleted && + responseCodeInterpreterCallInProgress == other.responseCodeInterpreterCallInProgress && + responseCodeInterpreterCallInterpreting == + other.responseCodeInterpreterCallInterpreting && + responseCompleted == other.responseCompleted && + responseContentPartAdded == other.responseContentPartAdded && + responseContentPartDone == other.responseContentPartDone && + responseCreated == other.responseCreated && + error == other.error && + responseFileSearchCallCompleted == other.responseFileSearchCallCompleted && + responseFileSearchCallInProgress == other.responseFileSearchCallInProgress && + responseFileSearchCallSearching == other.responseFileSearchCallSearching && + responseFunctionCallArgumentsDelta == other.responseFunctionCallArgumentsDelta && + responseFunctionCallArgumentsDone == other.responseFunctionCallArgumentsDone && + responseInProgress == other.responseInProgress && + responseFailed == other.responseFailed && + responseIncomplete == other.responseIncomplete && + responseOutputItemAdded == other.responseOutputItemAdded && + responseOutputItemDone == other.responseOutputItemDone && + responseReasoningSummaryPartAdded == other.responseReasoningSummaryPartAdded && + responseReasoningSummaryPartDone == other.responseReasoningSummaryPartDone && + responseReasoningSummaryTextDelta == other.responseReasoningSummaryTextDelta && + responseReasoningSummaryTextDone == other.responseReasoningSummaryTextDone && + responseReasoningTextDelta == other.responseReasoningTextDelta && + responseReasoningTextDone == other.responseReasoningTextDone && + responseRefusalDelta == other.responseRefusalDelta && + responseRefusalDone == other.responseRefusalDone && + responseOutputTextDelta == other.responseOutputTextDelta && + responseOutputTextDone == other.responseOutputTextDone && + responseWebSearchCallCompleted == other.responseWebSearchCallCompleted && + responseWebSearchCallInProgress == other.responseWebSearchCallInProgress && + responseWebSearchCallSearching == other.responseWebSearchCallSearching && + responseImageGenerationCallCompleted == other.responseImageGenerationCallCompleted && + responseImageGenerationCallGenerating == other.responseImageGenerationCallGenerating && + responseImageGenerationCallInProgress == other.responseImageGenerationCallInProgress && + responseImageGenerationCallPartialImage == + other.responseImageGenerationCallPartialImage && + responseMcpCallArgumentsDelta == other.responseMcpCallArgumentsDelta && + responseMcpCallArgumentsDone == other.responseMcpCallArgumentsDone && + responseMcpCallCompleted == other.responseMcpCallCompleted && + responseMcpCallFailed == other.responseMcpCallFailed && + responseMcpCallInProgress == other.responseMcpCallInProgress && + responseMcpListToolsCompleted == other.responseMcpListToolsCompleted && + responseMcpListToolsFailed == other.responseMcpListToolsFailed && + responseMcpListToolsInProgress == other.responseMcpListToolsInProgress && + responseOutputTextAnnotationAdded == other.responseOutputTextAnnotationAdded && + responseQueued == other.responseQueued && + responseCustomToolCallInputDelta == other.responseCustomToolCallInputDelta && + responseCustomToolCallInputDone == other.responseCustomToolCallInputDone + } + + override fun hashCode(): Int = + Objects.hash( + responseAudioDelta, + responseAudioDone, + responseAudioTranscriptDelta, + responseAudioTranscriptDone, + responseCodeInterpreterCallCodeDelta, + responseCodeInterpreterCallCodeDone, + responseCodeInterpreterCallCompleted, + responseCodeInterpreterCallInProgress, + responseCodeInterpreterCallInterpreting, + responseCompleted, + responseContentPartAdded, + responseContentPartDone, + responseCreated, + error, + responseFileSearchCallCompleted, + responseFileSearchCallInProgress, + responseFileSearchCallSearching, + responseFunctionCallArgumentsDelta, + responseFunctionCallArgumentsDone, + responseInProgress, + responseFailed, + responseIncomplete, + responseOutputItemAdded, + responseOutputItemDone, + responseReasoningSummaryPartAdded, + responseReasoningSummaryPartDone, + responseReasoningSummaryTextDelta, + responseReasoningSummaryTextDone, + responseReasoningTextDelta, + responseReasoningTextDone, + responseRefusalDelta, + responseRefusalDone, + responseOutputTextDelta, + responseOutputTextDone, + responseWebSearchCallCompleted, + responseWebSearchCallInProgress, + responseWebSearchCallSearching, + responseImageGenerationCallCompleted, + responseImageGenerationCallGenerating, + responseImageGenerationCallInProgress, + responseImageGenerationCallPartialImage, + responseMcpCallArgumentsDelta, + responseMcpCallArgumentsDone, + responseMcpCallCompleted, + responseMcpCallFailed, + responseMcpCallInProgress, + responseMcpListToolsCompleted, + responseMcpListToolsFailed, + responseMcpListToolsInProgress, + responseOutputTextAnnotationAdded, + responseQueued, + responseCustomToolCallInputDelta, + responseCustomToolCallInputDone, + ) + + override fun toString(): String = + when { + responseAudioDelta != null -> + "ResponsesServerEvent{responseAudioDelta=$responseAudioDelta}" + responseAudioDone != null -> + "ResponsesServerEvent{responseAudioDone=$responseAudioDone}" + responseAudioTranscriptDelta != null -> + "ResponsesServerEvent{responseAudioTranscriptDelta=$responseAudioTranscriptDelta}" + responseAudioTranscriptDone != null -> + "ResponsesServerEvent{responseAudioTranscriptDone=$responseAudioTranscriptDone}" + responseCodeInterpreterCallCodeDelta != null -> + "ResponsesServerEvent{responseCodeInterpreterCallCodeDelta=$responseCodeInterpreterCallCodeDelta}" + responseCodeInterpreterCallCodeDone != null -> + "ResponsesServerEvent{responseCodeInterpreterCallCodeDone=$responseCodeInterpreterCallCodeDone}" + responseCodeInterpreterCallCompleted != null -> + "ResponsesServerEvent{responseCodeInterpreterCallCompleted=$responseCodeInterpreterCallCompleted}" + responseCodeInterpreterCallInProgress != null -> + "ResponsesServerEvent{responseCodeInterpreterCallInProgress=$responseCodeInterpreterCallInProgress}" + responseCodeInterpreterCallInterpreting != null -> + "ResponsesServerEvent{responseCodeInterpreterCallInterpreting=$responseCodeInterpreterCallInterpreting}" + responseCompleted != null -> + "ResponsesServerEvent{responseCompleted=$responseCompleted}" + responseContentPartAdded != null -> + "ResponsesServerEvent{responseContentPartAdded=$responseContentPartAdded}" + responseContentPartDone != null -> + "ResponsesServerEvent{responseContentPartDone=$responseContentPartDone}" + responseCreated != null -> "ResponsesServerEvent{responseCreated=$responseCreated}" + error != null -> "ResponsesServerEvent{error=$error}" + responseFileSearchCallCompleted != null -> + "ResponsesServerEvent{responseFileSearchCallCompleted=$responseFileSearchCallCompleted}" + responseFileSearchCallInProgress != null -> + "ResponsesServerEvent{responseFileSearchCallInProgress=$responseFileSearchCallInProgress}" + responseFileSearchCallSearching != null -> + "ResponsesServerEvent{responseFileSearchCallSearching=$responseFileSearchCallSearching}" + responseFunctionCallArgumentsDelta != null -> + "ResponsesServerEvent{responseFunctionCallArgumentsDelta=$responseFunctionCallArgumentsDelta}" + responseFunctionCallArgumentsDone != null -> + "ResponsesServerEvent{responseFunctionCallArgumentsDone=$responseFunctionCallArgumentsDone}" + responseInProgress != null -> + "ResponsesServerEvent{responseInProgress=$responseInProgress}" + responseFailed != null -> "ResponsesServerEvent{responseFailed=$responseFailed}" + responseIncomplete != null -> + "ResponsesServerEvent{responseIncomplete=$responseIncomplete}" + responseOutputItemAdded != null -> + "ResponsesServerEvent{responseOutputItemAdded=$responseOutputItemAdded}" + responseOutputItemDone != null -> + "ResponsesServerEvent{responseOutputItemDone=$responseOutputItemDone}" + responseReasoningSummaryPartAdded != null -> + "ResponsesServerEvent{responseReasoningSummaryPartAdded=$responseReasoningSummaryPartAdded}" + responseReasoningSummaryPartDone != null -> + "ResponsesServerEvent{responseReasoningSummaryPartDone=$responseReasoningSummaryPartDone}" + responseReasoningSummaryTextDelta != null -> + "ResponsesServerEvent{responseReasoningSummaryTextDelta=$responseReasoningSummaryTextDelta}" + responseReasoningSummaryTextDone != null -> + "ResponsesServerEvent{responseReasoningSummaryTextDone=$responseReasoningSummaryTextDone}" + responseReasoningTextDelta != null -> + "ResponsesServerEvent{responseReasoningTextDelta=$responseReasoningTextDelta}" + responseReasoningTextDone != null -> + "ResponsesServerEvent{responseReasoningTextDone=$responseReasoningTextDone}" + responseRefusalDelta != null -> + "ResponsesServerEvent{responseRefusalDelta=$responseRefusalDelta}" + responseRefusalDone != null -> + "ResponsesServerEvent{responseRefusalDone=$responseRefusalDone}" + responseOutputTextDelta != null -> + "ResponsesServerEvent{responseOutputTextDelta=$responseOutputTextDelta}" + responseOutputTextDone != null -> + "ResponsesServerEvent{responseOutputTextDone=$responseOutputTextDone}" + responseWebSearchCallCompleted != null -> + "ResponsesServerEvent{responseWebSearchCallCompleted=$responseWebSearchCallCompleted}" + responseWebSearchCallInProgress != null -> + "ResponsesServerEvent{responseWebSearchCallInProgress=$responseWebSearchCallInProgress}" + responseWebSearchCallSearching != null -> + "ResponsesServerEvent{responseWebSearchCallSearching=$responseWebSearchCallSearching}" + responseImageGenerationCallCompleted != null -> + "ResponsesServerEvent{responseImageGenerationCallCompleted=$responseImageGenerationCallCompleted}" + responseImageGenerationCallGenerating != null -> + "ResponsesServerEvent{responseImageGenerationCallGenerating=$responseImageGenerationCallGenerating}" + responseImageGenerationCallInProgress != null -> + "ResponsesServerEvent{responseImageGenerationCallInProgress=$responseImageGenerationCallInProgress}" + responseImageGenerationCallPartialImage != null -> + "ResponsesServerEvent{responseImageGenerationCallPartialImage=$responseImageGenerationCallPartialImage}" + responseMcpCallArgumentsDelta != null -> + "ResponsesServerEvent{responseMcpCallArgumentsDelta=$responseMcpCallArgumentsDelta}" + responseMcpCallArgumentsDone != null -> + "ResponsesServerEvent{responseMcpCallArgumentsDone=$responseMcpCallArgumentsDone}" + responseMcpCallCompleted != null -> + "ResponsesServerEvent{responseMcpCallCompleted=$responseMcpCallCompleted}" + responseMcpCallFailed != null -> + "ResponsesServerEvent{responseMcpCallFailed=$responseMcpCallFailed}" + responseMcpCallInProgress != null -> + "ResponsesServerEvent{responseMcpCallInProgress=$responseMcpCallInProgress}" + responseMcpListToolsCompleted != null -> + "ResponsesServerEvent{responseMcpListToolsCompleted=$responseMcpListToolsCompleted}" + responseMcpListToolsFailed != null -> + "ResponsesServerEvent{responseMcpListToolsFailed=$responseMcpListToolsFailed}" + responseMcpListToolsInProgress != null -> + "ResponsesServerEvent{responseMcpListToolsInProgress=$responseMcpListToolsInProgress}" + responseOutputTextAnnotationAdded != null -> + "ResponsesServerEvent{responseOutputTextAnnotationAdded=$responseOutputTextAnnotationAdded}" + responseQueued != null -> "ResponsesServerEvent{responseQueued=$responseQueued}" + responseCustomToolCallInputDelta != null -> + "ResponsesServerEvent{responseCustomToolCallInputDelta=$responseCustomToolCallInputDelta}" + responseCustomToolCallInputDone != null -> + "ResponsesServerEvent{responseCustomToolCallInputDone=$responseCustomToolCallInputDone}" + _json != null -> "ResponsesServerEvent{_unknown=$_json}" + else -> throw IllegalStateException("Invalid ResponsesServerEvent") + } + + companion object { + + /** Emitted when there is a partial audio response. */ + @JvmStatic + fun ofResponseAudioDelta(responseAudioDelta: ResponseAudioDeltaEvent) = + ResponsesServerEvent(responseAudioDelta = responseAudioDelta) + + /** Emitted when the audio response is complete. */ + @JvmStatic + fun ofResponseAudioDone(responseAudioDone: ResponseAudioDoneEvent) = + ResponsesServerEvent(responseAudioDone = responseAudioDone) + + /** Emitted when there is a partial transcript of audio. */ + @JvmStatic + fun ofResponseAudioTranscriptDelta( + responseAudioTranscriptDelta: ResponseAudioTranscriptDeltaEvent + ) = ResponsesServerEvent(responseAudioTranscriptDelta = responseAudioTranscriptDelta) + + /** Emitted when the full audio transcript is completed. */ + @JvmStatic + fun ofResponseAudioTranscriptDone( + responseAudioTranscriptDone: ResponseAudioTranscriptDoneEvent + ) = ResponsesServerEvent(responseAudioTranscriptDone = responseAudioTranscriptDone) + + /** Emitted when a partial code snippet is streamed by the code interpreter. */ + @JvmStatic + fun ofResponseCodeInterpreterCallCodeDelta( + responseCodeInterpreterCallCodeDelta: ResponseCodeInterpreterCallCodeDeltaEvent + ) = + ResponsesServerEvent( + responseCodeInterpreterCallCodeDelta = responseCodeInterpreterCallCodeDelta + ) + + /** Emitted when the code snippet is finalized by the code interpreter. */ + @JvmStatic + fun ofResponseCodeInterpreterCallCodeDone( + responseCodeInterpreterCallCodeDone: ResponseCodeInterpreterCallCodeDoneEvent + ) = + ResponsesServerEvent( + responseCodeInterpreterCallCodeDone = responseCodeInterpreterCallCodeDone + ) + + /** Emitted when the code interpreter call is completed. */ + @JvmStatic + fun ofResponseCodeInterpreterCallCompleted( + responseCodeInterpreterCallCompleted: ResponseCodeInterpreterCallCompletedEvent + ) = + ResponsesServerEvent( + responseCodeInterpreterCallCompleted = responseCodeInterpreterCallCompleted + ) + + /** Emitted when a code interpreter call is in progress. */ + @JvmStatic + fun ofResponseCodeInterpreterCallInProgress( + responseCodeInterpreterCallInProgress: ResponseCodeInterpreterCallInProgressEvent + ) = + ResponsesServerEvent( + responseCodeInterpreterCallInProgress = responseCodeInterpreterCallInProgress + ) + + /** Emitted when the code interpreter is actively interpreting the code snippet. */ + @JvmStatic + fun ofResponseCodeInterpreterCallInterpreting( + responseCodeInterpreterCallInterpreting: ResponseCodeInterpreterCallInterpretingEvent + ) = + ResponsesServerEvent( + responseCodeInterpreterCallInterpreting = responseCodeInterpreterCallInterpreting + ) + + /** Emitted when the model response is complete. */ + @JvmStatic + fun ofResponseCompleted(responseCompleted: ResponseCompletedEvent) = + ResponsesServerEvent(responseCompleted = responseCompleted) + + /** Emitted when a new content part is added. */ + @JvmStatic + fun ofResponseContentPartAdded(responseContentPartAdded: ResponseContentPartAddedEvent) = + ResponsesServerEvent(responseContentPartAdded = responseContentPartAdded) + + /** Emitted when a content part is done. */ + @JvmStatic + fun ofResponseContentPartDone(responseContentPartDone: ResponseContentPartDoneEvent) = + ResponsesServerEvent(responseContentPartDone = responseContentPartDone) + + /** An event that is emitted when a response is created. */ + @JvmStatic + fun ofResponseCreated(responseCreated: ResponseCreatedEvent) = + ResponsesServerEvent(responseCreated = responseCreated) + + /** Emitted when an error occurs. */ + @JvmStatic fun ofError(error: ResponseErrorEvent) = ResponsesServerEvent(error = error) + + /** Emitted when a file search call is completed (results found). */ + @JvmStatic + fun ofResponseFileSearchCallCompleted( + responseFileSearchCallCompleted: ResponseFileSearchCallCompletedEvent + ) = ResponsesServerEvent(responseFileSearchCallCompleted = responseFileSearchCallCompleted) + + /** Emitted when a file search call is initiated. */ + @JvmStatic + fun ofResponseFileSearchCallInProgress( + responseFileSearchCallInProgress: ResponseFileSearchCallInProgressEvent + ) = + ResponsesServerEvent( + responseFileSearchCallInProgress = responseFileSearchCallInProgress + ) + + /** Emitted when a file search is currently searching. */ + @JvmStatic + fun ofResponseFileSearchCallSearching( + responseFileSearchCallSearching: ResponseFileSearchCallSearchingEvent + ) = ResponsesServerEvent(responseFileSearchCallSearching = responseFileSearchCallSearching) + + /** Emitted when there is a partial function-call arguments delta. */ + @JvmStatic + fun ofResponseFunctionCallArgumentsDelta( + responseFunctionCallArgumentsDelta: ResponseFunctionCallArgumentsDeltaEvent + ) = + ResponsesServerEvent( + responseFunctionCallArgumentsDelta = responseFunctionCallArgumentsDelta + ) + + /** Emitted when function-call arguments are finalized. */ + @JvmStatic + fun ofResponseFunctionCallArgumentsDone( + responseFunctionCallArgumentsDone: ResponseFunctionCallArgumentsDoneEvent + ) = + ResponsesServerEvent( + responseFunctionCallArgumentsDone = responseFunctionCallArgumentsDone + ) + + /** Emitted when the response is in progress. */ + @JvmStatic + fun ofResponseInProgress(responseInProgress: ResponseInProgressEvent) = + ResponsesServerEvent(responseInProgress = responseInProgress) + + /** An event that is emitted when a response fails. */ + @JvmStatic + fun ofResponseFailed(responseFailed: ResponseFailedEvent) = + ResponsesServerEvent(responseFailed = responseFailed) + + /** An event that is emitted when a response finishes as incomplete. */ + @JvmStatic + fun ofResponseIncomplete(responseIncomplete: ResponseIncompleteEvent) = + ResponsesServerEvent(responseIncomplete = responseIncomplete) + + /** Emitted when a new output item is added. */ + @JvmStatic + fun ofResponseOutputItemAdded(responseOutputItemAdded: ResponseOutputItemAddedEvent) = + ResponsesServerEvent(responseOutputItemAdded = responseOutputItemAdded) + + /** Emitted when an output item is marked done. */ + @JvmStatic + fun ofResponseOutputItemDone(responseOutputItemDone: ResponseOutputItemDoneEvent) = + ResponsesServerEvent(responseOutputItemDone = responseOutputItemDone) + + /** Emitted when a new reasoning summary part is added. */ + @JvmStatic + fun ofResponseReasoningSummaryPartAdded( + responseReasoningSummaryPartAdded: ResponseReasoningSummaryPartAddedEvent + ) = + ResponsesServerEvent( + responseReasoningSummaryPartAdded = responseReasoningSummaryPartAdded + ) + + /** Emitted when a reasoning summary part is completed. */ + @JvmStatic + fun ofResponseReasoningSummaryPartDone( + responseReasoningSummaryPartDone: ResponseReasoningSummaryPartDoneEvent + ) = + ResponsesServerEvent( + responseReasoningSummaryPartDone = responseReasoningSummaryPartDone + ) + + /** Emitted when a delta is added to a reasoning summary text. */ + @JvmStatic + fun ofResponseReasoningSummaryTextDelta( + responseReasoningSummaryTextDelta: ResponseReasoningSummaryTextDeltaEvent + ) = + ResponsesServerEvent( + responseReasoningSummaryTextDelta = responseReasoningSummaryTextDelta + ) + + /** Emitted when a reasoning summary text is completed. */ + @JvmStatic + fun ofResponseReasoningSummaryTextDone( + responseReasoningSummaryTextDone: ResponseReasoningSummaryTextDoneEvent + ) = + ResponsesServerEvent( + responseReasoningSummaryTextDone = responseReasoningSummaryTextDone + ) + + /** Emitted when a delta is added to a reasoning text. */ + @JvmStatic + fun ofResponseReasoningTextDelta( + responseReasoningTextDelta: ResponseReasoningTextDeltaEvent + ) = ResponsesServerEvent(responseReasoningTextDelta = responseReasoningTextDelta) + + /** Emitted when a reasoning text is completed. */ + @JvmStatic + fun ofResponseReasoningTextDone(responseReasoningTextDone: ResponseReasoningTextDoneEvent) = + ResponsesServerEvent(responseReasoningTextDone = responseReasoningTextDone) + + /** Emitted when there is a partial refusal text. */ + @JvmStatic + fun ofResponseRefusalDelta(responseRefusalDelta: ResponseRefusalDeltaEvent) = + ResponsesServerEvent(responseRefusalDelta = responseRefusalDelta) + + /** Emitted when refusal text is finalized. */ + @JvmStatic + fun ofResponseRefusalDone(responseRefusalDone: ResponseRefusalDoneEvent) = + ResponsesServerEvent(responseRefusalDone = responseRefusalDone) + + /** Emitted when there is an additional text delta. */ + @JvmStatic + fun ofResponseOutputTextDelta(responseOutputTextDelta: ResponseTextDeltaEvent) = + ResponsesServerEvent(responseOutputTextDelta = responseOutputTextDelta) + + /** Emitted when text content is finalized. */ + @JvmStatic + fun ofResponseOutputTextDone(responseOutputTextDone: ResponseTextDoneEvent) = + ResponsesServerEvent(responseOutputTextDone = responseOutputTextDone) + + /** Emitted when a web search call is completed. */ + @JvmStatic + fun ofResponseWebSearchCallCompleted( + responseWebSearchCallCompleted: ResponseWebSearchCallCompletedEvent + ) = ResponsesServerEvent(responseWebSearchCallCompleted = responseWebSearchCallCompleted) + + /** Emitted when a web search call is initiated. */ + @JvmStatic + fun ofResponseWebSearchCallInProgress( + responseWebSearchCallInProgress: ResponseWebSearchCallInProgressEvent + ) = ResponsesServerEvent(responseWebSearchCallInProgress = responseWebSearchCallInProgress) + + /** Emitted when a web search call is executing. */ + @JvmStatic + fun ofResponseWebSearchCallSearching( + responseWebSearchCallSearching: ResponseWebSearchCallSearchingEvent + ) = ResponsesServerEvent(responseWebSearchCallSearching = responseWebSearchCallSearching) + + /** + * Emitted when an image generation tool call has completed and the final image is + * available. + */ + @JvmStatic + fun ofResponseImageGenerationCallCompleted( + responseImageGenerationCallCompleted: ResponseImageGenCallCompletedEvent + ) = + ResponsesServerEvent( + responseImageGenerationCallCompleted = responseImageGenerationCallCompleted + ) + + /** + * Emitted when an image generation tool call is actively generating an image (intermediate + * state). + */ + @JvmStatic + fun ofResponseImageGenerationCallGenerating( + responseImageGenerationCallGenerating: ResponseImageGenCallGeneratingEvent + ) = + ResponsesServerEvent( + responseImageGenerationCallGenerating = responseImageGenerationCallGenerating + ) + + /** Emitted when an image generation tool call is in progress. */ + @JvmStatic + fun ofResponseImageGenerationCallInProgress( + responseImageGenerationCallInProgress: ResponseImageGenCallInProgressEvent + ) = + ResponsesServerEvent( + responseImageGenerationCallInProgress = responseImageGenerationCallInProgress + ) + + /** Emitted when a partial image is available during image generation streaming. */ + @JvmStatic + fun ofResponseImageGenerationCallPartialImage( + responseImageGenerationCallPartialImage: ResponseImageGenCallPartialImageEvent + ) = + ResponsesServerEvent( + responseImageGenerationCallPartialImage = responseImageGenerationCallPartialImage + ) + + /** Emitted when there is a delta (partial update) to the arguments of an MCP tool call. */ + @JvmStatic + fun ofResponseMcpCallArgumentsDelta( + responseMcpCallArgumentsDelta: ResponseMcpCallArgumentsDeltaEvent + ) = ResponsesServerEvent(responseMcpCallArgumentsDelta = responseMcpCallArgumentsDelta) + + /** Emitted when the arguments for an MCP tool call are finalized. */ + @JvmStatic + fun ofResponseMcpCallArgumentsDone( + responseMcpCallArgumentsDone: ResponseMcpCallArgumentsDoneEvent + ) = ResponsesServerEvent(responseMcpCallArgumentsDone = responseMcpCallArgumentsDone) + + /** Emitted when an MCP tool call has completed successfully. */ + @JvmStatic + fun ofResponseMcpCallCompleted(responseMcpCallCompleted: ResponseMcpCallCompletedEvent) = + ResponsesServerEvent(responseMcpCallCompleted = responseMcpCallCompleted) + + /** Emitted when an MCP tool call has failed. */ + @JvmStatic + fun ofResponseMcpCallFailed(responseMcpCallFailed: ResponseMcpCallFailedEvent) = + ResponsesServerEvent(responseMcpCallFailed = responseMcpCallFailed) + + /** Emitted when an MCP tool call is in progress. */ + @JvmStatic + fun ofResponseMcpCallInProgress(responseMcpCallInProgress: ResponseMcpCallInProgressEvent) = + ResponsesServerEvent(responseMcpCallInProgress = responseMcpCallInProgress) + + /** Emitted when the list of available MCP tools has been successfully retrieved. */ + @JvmStatic + fun ofResponseMcpListToolsCompleted( + responseMcpListToolsCompleted: ResponseMcpListToolsCompletedEvent + ) = ResponsesServerEvent(responseMcpListToolsCompleted = responseMcpListToolsCompleted) + + /** Emitted when the attempt to list available MCP tools has failed. */ + @JvmStatic + fun ofResponseMcpListToolsFailed( + responseMcpListToolsFailed: ResponseMcpListToolsFailedEvent + ) = ResponsesServerEvent(responseMcpListToolsFailed = responseMcpListToolsFailed) + + /** + * Emitted when the system is in the process of retrieving the list of available MCP tools. + */ + @JvmStatic + fun ofResponseMcpListToolsInProgress( + responseMcpListToolsInProgress: ResponseMcpListToolsInProgressEvent + ) = ResponsesServerEvent(responseMcpListToolsInProgress = responseMcpListToolsInProgress) + + /** Emitted when an annotation is added to output text content. */ + @JvmStatic + fun ofResponseOutputTextAnnotationAdded( + responseOutputTextAnnotationAdded: ResponseOutputTextAnnotationAddedEvent + ) = + ResponsesServerEvent( + responseOutputTextAnnotationAdded = responseOutputTextAnnotationAdded + ) + + /** Emitted when a response is queued and waiting to be processed. */ + @JvmStatic + fun ofResponseQueued(responseQueued: ResponseQueuedEvent) = + ResponsesServerEvent(responseQueued = responseQueued) + + /** Event representing a delta (partial update) to the input of a custom tool call. */ + @JvmStatic + fun ofResponseCustomToolCallInputDelta( + responseCustomToolCallInputDelta: ResponseCustomToolCallInputDeltaEvent + ) = + ResponsesServerEvent( + responseCustomToolCallInputDelta = responseCustomToolCallInputDelta + ) + + /** Event indicating that input for a custom tool call is complete. */ + @JvmStatic + fun ofResponseCustomToolCallInputDone( + responseCustomToolCallInputDone: ResponseCustomToolCallInputDoneEvent + ) = ResponsesServerEvent(responseCustomToolCallInputDone = responseCustomToolCallInputDone) + } + + /** + * An interface that defines how to map each variant of [ResponsesServerEvent] to a value of + * type [T]. + */ + interface Visitor { + + /** Emitted when there is a partial audio response. */ + fun visitResponseAudioDelta(responseAudioDelta: ResponseAudioDeltaEvent): T + + /** Emitted when the audio response is complete. */ + fun visitResponseAudioDone(responseAudioDone: ResponseAudioDoneEvent): T + + /** Emitted when there is a partial transcript of audio. */ + fun visitResponseAudioTranscriptDelta( + responseAudioTranscriptDelta: ResponseAudioTranscriptDeltaEvent + ): T + + /** Emitted when the full audio transcript is completed. */ + fun visitResponseAudioTranscriptDone( + responseAudioTranscriptDone: ResponseAudioTranscriptDoneEvent + ): T + + /** Emitted when a partial code snippet is streamed by the code interpreter. */ + fun visitResponseCodeInterpreterCallCodeDelta( + responseCodeInterpreterCallCodeDelta: ResponseCodeInterpreterCallCodeDeltaEvent + ): T + + /** Emitted when the code snippet is finalized by the code interpreter. */ + fun visitResponseCodeInterpreterCallCodeDone( + responseCodeInterpreterCallCodeDone: ResponseCodeInterpreterCallCodeDoneEvent + ): T + + /** Emitted when the code interpreter call is completed. */ + fun visitResponseCodeInterpreterCallCompleted( + responseCodeInterpreterCallCompleted: ResponseCodeInterpreterCallCompletedEvent + ): T + + /** Emitted when a code interpreter call is in progress. */ + fun visitResponseCodeInterpreterCallInProgress( + responseCodeInterpreterCallInProgress: ResponseCodeInterpreterCallInProgressEvent + ): T + + /** Emitted when the code interpreter is actively interpreting the code snippet. */ + fun visitResponseCodeInterpreterCallInterpreting( + responseCodeInterpreterCallInterpreting: ResponseCodeInterpreterCallInterpretingEvent + ): T + + /** Emitted when the model response is complete. */ + fun visitResponseCompleted(responseCompleted: ResponseCompletedEvent): T + + /** Emitted when a new content part is added. */ + fun visitResponseContentPartAdded( + responseContentPartAdded: ResponseContentPartAddedEvent + ): T + + /** Emitted when a content part is done. */ + fun visitResponseContentPartDone(responseContentPartDone: ResponseContentPartDoneEvent): T + + /** An event that is emitted when a response is created. */ + fun visitResponseCreated(responseCreated: ResponseCreatedEvent): T + + /** Emitted when an error occurs. */ + fun visitError(error: ResponseErrorEvent): T + + /** Emitted when a file search call is completed (results found). */ + fun visitResponseFileSearchCallCompleted( + responseFileSearchCallCompleted: ResponseFileSearchCallCompletedEvent + ): T + + /** Emitted when a file search call is initiated. */ + fun visitResponseFileSearchCallInProgress( + responseFileSearchCallInProgress: ResponseFileSearchCallInProgressEvent + ): T + + /** Emitted when a file search is currently searching. */ + fun visitResponseFileSearchCallSearching( + responseFileSearchCallSearching: ResponseFileSearchCallSearchingEvent + ): T + + /** Emitted when there is a partial function-call arguments delta. */ + fun visitResponseFunctionCallArgumentsDelta( + responseFunctionCallArgumentsDelta: ResponseFunctionCallArgumentsDeltaEvent + ): T + + /** Emitted when function-call arguments are finalized. */ + fun visitResponseFunctionCallArgumentsDone( + responseFunctionCallArgumentsDone: ResponseFunctionCallArgumentsDoneEvent + ): T + + /** Emitted when the response is in progress. */ + fun visitResponseInProgress(responseInProgress: ResponseInProgressEvent): T + + /** An event that is emitted when a response fails. */ + fun visitResponseFailed(responseFailed: ResponseFailedEvent): T + + /** An event that is emitted when a response finishes as incomplete. */ + fun visitResponseIncomplete(responseIncomplete: ResponseIncompleteEvent): T + + /** Emitted when a new output item is added. */ + fun visitResponseOutputItemAdded(responseOutputItemAdded: ResponseOutputItemAddedEvent): T + + /** Emitted when an output item is marked done. */ + fun visitResponseOutputItemDone(responseOutputItemDone: ResponseOutputItemDoneEvent): T + + /** Emitted when a new reasoning summary part is added. */ + fun visitResponseReasoningSummaryPartAdded( + responseReasoningSummaryPartAdded: ResponseReasoningSummaryPartAddedEvent + ): T + + /** Emitted when a reasoning summary part is completed. */ + fun visitResponseReasoningSummaryPartDone( + responseReasoningSummaryPartDone: ResponseReasoningSummaryPartDoneEvent + ): T + + /** Emitted when a delta is added to a reasoning summary text. */ + fun visitResponseReasoningSummaryTextDelta( + responseReasoningSummaryTextDelta: ResponseReasoningSummaryTextDeltaEvent + ): T + + /** Emitted when a reasoning summary text is completed. */ + fun visitResponseReasoningSummaryTextDone( + responseReasoningSummaryTextDone: ResponseReasoningSummaryTextDoneEvent + ): T + + /** Emitted when a delta is added to a reasoning text. */ + fun visitResponseReasoningTextDelta( + responseReasoningTextDelta: ResponseReasoningTextDeltaEvent + ): T + + /** Emitted when a reasoning text is completed. */ + fun visitResponseReasoningTextDone( + responseReasoningTextDone: ResponseReasoningTextDoneEvent + ): T + + /** Emitted when there is a partial refusal text. */ + fun visitResponseRefusalDelta(responseRefusalDelta: ResponseRefusalDeltaEvent): T + + /** Emitted when refusal text is finalized. */ + fun visitResponseRefusalDone(responseRefusalDone: ResponseRefusalDoneEvent): T + + /** Emitted when there is an additional text delta. */ + fun visitResponseOutputTextDelta(responseOutputTextDelta: ResponseTextDeltaEvent): T + + /** Emitted when text content is finalized. */ + fun visitResponseOutputTextDone(responseOutputTextDone: ResponseTextDoneEvent): T + + /** Emitted when a web search call is completed. */ + fun visitResponseWebSearchCallCompleted( + responseWebSearchCallCompleted: ResponseWebSearchCallCompletedEvent + ): T + + /** Emitted when a web search call is initiated. */ + fun visitResponseWebSearchCallInProgress( + responseWebSearchCallInProgress: ResponseWebSearchCallInProgressEvent + ): T + + /** Emitted when a web search call is executing. */ + fun visitResponseWebSearchCallSearching( + responseWebSearchCallSearching: ResponseWebSearchCallSearchingEvent + ): T + + /** + * Emitted when an image generation tool call has completed and the final image is + * available. + */ + fun visitResponseImageGenerationCallCompleted( + responseImageGenerationCallCompleted: ResponseImageGenCallCompletedEvent + ): T + + /** + * Emitted when an image generation tool call is actively generating an image (intermediate + * state). + */ + fun visitResponseImageGenerationCallGenerating( + responseImageGenerationCallGenerating: ResponseImageGenCallGeneratingEvent + ): T + + /** Emitted when an image generation tool call is in progress. */ + fun visitResponseImageGenerationCallInProgress( + responseImageGenerationCallInProgress: ResponseImageGenCallInProgressEvent + ): T + + /** Emitted when a partial image is available during image generation streaming. */ + fun visitResponseImageGenerationCallPartialImage( + responseImageGenerationCallPartialImage: ResponseImageGenCallPartialImageEvent + ): T + + /** Emitted when there is a delta (partial update) to the arguments of an MCP tool call. */ + fun visitResponseMcpCallArgumentsDelta( + responseMcpCallArgumentsDelta: ResponseMcpCallArgumentsDeltaEvent + ): T + + /** Emitted when the arguments for an MCP tool call are finalized. */ + fun visitResponseMcpCallArgumentsDone( + responseMcpCallArgumentsDone: ResponseMcpCallArgumentsDoneEvent + ): T + + /** Emitted when an MCP tool call has completed successfully. */ + fun visitResponseMcpCallCompleted( + responseMcpCallCompleted: ResponseMcpCallCompletedEvent + ): T + + /** Emitted when an MCP tool call has failed. */ + fun visitResponseMcpCallFailed(responseMcpCallFailed: ResponseMcpCallFailedEvent): T + + /** Emitted when an MCP tool call is in progress. */ + fun visitResponseMcpCallInProgress( + responseMcpCallInProgress: ResponseMcpCallInProgressEvent + ): T + + /** Emitted when the list of available MCP tools has been successfully retrieved. */ + fun visitResponseMcpListToolsCompleted( + responseMcpListToolsCompleted: ResponseMcpListToolsCompletedEvent + ): T + + /** Emitted when the attempt to list available MCP tools has failed. */ + fun visitResponseMcpListToolsFailed( + responseMcpListToolsFailed: ResponseMcpListToolsFailedEvent + ): T + + /** + * Emitted when the system is in the process of retrieving the list of available MCP tools. + */ + fun visitResponseMcpListToolsInProgress( + responseMcpListToolsInProgress: ResponseMcpListToolsInProgressEvent + ): T + + /** Emitted when an annotation is added to output text content. */ + fun visitResponseOutputTextAnnotationAdded( + responseOutputTextAnnotationAdded: ResponseOutputTextAnnotationAddedEvent + ): T + + /** Emitted when a response is queued and waiting to be processed. */ + fun visitResponseQueued(responseQueued: ResponseQueuedEvent): T + + /** Event representing a delta (partial update) to the input of a custom tool call. */ + fun visitResponseCustomToolCallInputDelta( + responseCustomToolCallInputDelta: ResponseCustomToolCallInputDeltaEvent + ): T + + /** Event indicating that input for a custom tool call is complete. */ + fun visitResponseCustomToolCallInputDone( + responseCustomToolCallInputDone: ResponseCustomToolCallInputDoneEvent + ): T + + /** + * Maps an unknown variant of [ResponsesServerEvent] to a value of type [T]. + * + * An instance of [ResponsesServerEvent] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if the SDK is + * on an older version than the API, then the API may respond with new variants that the SDK + * is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown ResponsesServerEvent: $json") + } + } + + internal class Deserializer : + BaseDeserializer(ResponsesServerEvent::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): ResponsesServerEvent { + val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() + + when (type) { + "response.audio.delta" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseAudioDelta = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.audio.done" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseAudioDone = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.audio.transcript.delta" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { + ResponsesServerEvent(responseAudioTranscriptDelta = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.audio.transcript.done" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { + ResponsesServerEvent(responseAudioTranscriptDone = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.code_interpreter_call_code.delta" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseCodeInterpreterCallCodeDelta = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.code_interpreter_call_code.done" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseCodeInterpreterCallCodeDone = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.code_interpreter_call.completed" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseCodeInterpreterCallCompleted = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.code_interpreter_call.in_progress" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseCodeInterpreterCallInProgress = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.code_interpreter_call.interpreting" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseCodeInterpreterCallInterpreting = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.completed" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseCompleted = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.content_part.added" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { ResponsesServerEvent(responseContentPartAdded = it, _json = json) } + ?: ResponsesServerEvent(_json = json) + } + "response.content_part.done" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { ResponsesServerEvent(responseContentPartDone = it, _json = json) } + ?: ResponsesServerEvent(_json = json) + } + "response.created" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseCreated = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "error" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(error = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.file_search_call.completed" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent(responseFileSearchCallCompleted = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.file_search_call.in_progress" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseFileSearchCallInProgress = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.file_search_call.searching" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent(responseFileSearchCallSearching = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.function_call_arguments.delta" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseFunctionCallArgumentsDelta = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.function_call_arguments.done" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseFunctionCallArgumentsDone = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.in_progress" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseInProgress = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.failed" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseFailed = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.incomplete" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseIncomplete = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.output_item.added" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { ResponsesServerEvent(responseOutputItemAdded = it, _json = json) } + ?: ResponsesServerEvent(_json = json) + } + "response.output_item.done" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { ResponsesServerEvent(responseOutputItemDone = it, _json = json) } + ?: ResponsesServerEvent(_json = json) + } + "response.reasoning_summary_part.added" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseReasoningSummaryPartAdded = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.reasoning_summary_part.done" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseReasoningSummaryPartDone = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.reasoning_summary_text.delta" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseReasoningSummaryTextDelta = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.reasoning_summary_text.done" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseReasoningSummaryTextDone = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.reasoning_text.delta" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { + ResponsesServerEvent(responseReasoningTextDelta = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.reasoning_text.done" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { ResponsesServerEvent(responseReasoningTextDone = it, _json = json) } + ?: ResponsesServerEvent(_json = json) + } + "response.refusal.delta" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseRefusalDelta = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.refusal.done" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseRefusalDone = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.output_text.delta" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseOutputTextDelta = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.output_text.done" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseOutputTextDone = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.web_search_call.completed" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent(responseWebSearchCallCompleted = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.web_search_call.in_progress" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent(responseWebSearchCallInProgress = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.web_search_call.searching" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent(responseWebSearchCallSearching = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.image_generation_call.completed" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseImageGenerationCallCompleted = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.image_generation_call.generating" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseImageGenerationCallGenerating = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.image_generation_call.in_progress" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseImageGenerationCallInProgress = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.image_generation_call.partial_image" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseImageGenerationCallPartialImage = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.mcp_call_arguments.delta" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent(responseMcpCallArgumentsDelta = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.mcp_call_arguments.done" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { + ResponsesServerEvent(responseMcpCallArgumentsDone = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.mcp_call.completed" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { ResponsesServerEvent(responseMcpCallCompleted = it, _json = json) } + ?: ResponsesServerEvent(_json = json) + } + "response.mcp_call.failed" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseMcpCallFailed = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.mcp_call.in_progress" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { ResponsesServerEvent(responseMcpCallInProgress = it, _json = json) } + ?: ResponsesServerEvent(_json = json) + } + "response.mcp_list_tools.completed" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent(responseMcpListToolsCompleted = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.mcp_list_tools.failed" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { + ResponsesServerEvent(responseMcpListToolsFailed = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.mcp_list_tools.in_progress" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent(responseMcpListToolsInProgress = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.output_text.annotation.added" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseOutputTextAnnotationAdded = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.queued" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ResponsesServerEvent(responseQueued = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + "response.custom_tool_call_input.delta" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent( + responseCustomToolCallInputDelta = it, + _json = json, + ) + } ?: ResponsesServerEvent(_json = json) + } + "response.custom_tool_call_input.done" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + ResponsesServerEvent(responseCustomToolCallInputDone = it, _json = json) + } ?: ResponsesServerEvent(_json = json) + } + } + + return ResponsesServerEvent(_json = json) + } + } + + internal class Serializer : BaseSerializer(ResponsesServerEvent::class) { + + override fun serialize( + value: ResponsesServerEvent, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.responseAudioDelta != null -> generator.writeObject(value.responseAudioDelta) + value.responseAudioDone != null -> generator.writeObject(value.responseAudioDone) + value.responseAudioTranscriptDelta != null -> + generator.writeObject(value.responseAudioTranscriptDelta) + value.responseAudioTranscriptDone != null -> + generator.writeObject(value.responseAudioTranscriptDone) + value.responseCodeInterpreterCallCodeDelta != null -> + generator.writeObject(value.responseCodeInterpreterCallCodeDelta) + value.responseCodeInterpreterCallCodeDone != null -> + generator.writeObject(value.responseCodeInterpreterCallCodeDone) + value.responseCodeInterpreterCallCompleted != null -> + generator.writeObject(value.responseCodeInterpreterCallCompleted) + value.responseCodeInterpreterCallInProgress != null -> + generator.writeObject(value.responseCodeInterpreterCallInProgress) + value.responseCodeInterpreterCallInterpreting != null -> + generator.writeObject(value.responseCodeInterpreterCallInterpreting) + value.responseCompleted != null -> generator.writeObject(value.responseCompleted) + value.responseContentPartAdded != null -> + generator.writeObject(value.responseContentPartAdded) + value.responseContentPartDone != null -> + generator.writeObject(value.responseContentPartDone) + value.responseCreated != null -> generator.writeObject(value.responseCreated) + value.error != null -> generator.writeObject(value.error) + value.responseFileSearchCallCompleted != null -> + generator.writeObject(value.responseFileSearchCallCompleted) + value.responseFileSearchCallInProgress != null -> + generator.writeObject(value.responseFileSearchCallInProgress) + value.responseFileSearchCallSearching != null -> + generator.writeObject(value.responseFileSearchCallSearching) + value.responseFunctionCallArgumentsDelta != null -> + generator.writeObject(value.responseFunctionCallArgumentsDelta) + value.responseFunctionCallArgumentsDone != null -> + generator.writeObject(value.responseFunctionCallArgumentsDone) + value.responseInProgress != null -> generator.writeObject(value.responseInProgress) + value.responseFailed != null -> generator.writeObject(value.responseFailed) + value.responseIncomplete != null -> generator.writeObject(value.responseIncomplete) + value.responseOutputItemAdded != null -> + generator.writeObject(value.responseOutputItemAdded) + value.responseOutputItemDone != null -> + generator.writeObject(value.responseOutputItemDone) + value.responseReasoningSummaryPartAdded != null -> + generator.writeObject(value.responseReasoningSummaryPartAdded) + value.responseReasoningSummaryPartDone != null -> + generator.writeObject(value.responseReasoningSummaryPartDone) + value.responseReasoningSummaryTextDelta != null -> + generator.writeObject(value.responseReasoningSummaryTextDelta) + value.responseReasoningSummaryTextDone != null -> + generator.writeObject(value.responseReasoningSummaryTextDone) + value.responseReasoningTextDelta != null -> + generator.writeObject(value.responseReasoningTextDelta) + value.responseReasoningTextDone != null -> + generator.writeObject(value.responseReasoningTextDone) + value.responseRefusalDelta != null -> + generator.writeObject(value.responseRefusalDelta) + value.responseRefusalDone != null -> + generator.writeObject(value.responseRefusalDone) + value.responseOutputTextDelta != null -> + generator.writeObject(value.responseOutputTextDelta) + value.responseOutputTextDone != null -> + generator.writeObject(value.responseOutputTextDone) + value.responseWebSearchCallCompleted != null -> + generator.writeObject(value.responseWebSearchCallCompleted) + value.responseWebSearchCallInProgress != null -> + generator.writeObject(value.responseWebSearchCallInProgress) + value.responseWebSearchCallSearching != null -> + generator.writeObject(value.responseWebSearchCallSearching) + value.responseImageGenerationCallCompleted != null -> + generator.writeObject(value.responseImageGenerationCallCompleted) + value.responseImageGenerationCallGenerating != null -> + generator.writeObject(value.responseImageGenerationCallGenerating) + value.responseImageGenerationCallInProgress != null -> + generator.writeObject(value.responseImageGenerationCallInProgress) + value.responseImageGenerationCallPartialImage != null -> + generator.writeObject(value.responseImageGenerationCallPartialImage) + value.responseMcpCallArgumentsDelta != null -> + generator.writeObject(value.responseMcpCallArgumentsDelta) + value.responseMcpCallArgumentsDone != null -> + generator.writeObject(value.responseMcpCallArgumentsDone) + value.responseMcpCallCompleted != null -> + generator.writeObject(value.responseMcpCallCompleted) + value.responseMcpCallFailed != null -> + generator.writeObject(value.responseMcpCallFailed) + value.responseMcpCallInProgress != null -> + generator.writeObject(value.responseMcpCallInProgress) + value.responseMcpListToolsCompleted != null -> + generator.writeObject(value.responseMcpListToolsCompleted) + value.responseMcpListToolsFailed != null -> + generator.writeObject(value.responseMcpListToolsFailed) + value.responseMcpListToolsInProgress != null -> + generator.writeObject(value.responseMcpListToolsInProgress) + value.responseOutputTextAnnotationAdded != null -> + generator.writeObject(value.responseOutputTextAnnotationAdded) + value.responseQueued != null -> generator.writeObject(value.responseQueued) + value.responseCustomToolCallInputDelta != null -> + generator.writeObject(value.responseCustomToolCallInputDelta) + value.responseCustomToolCallInputDone != null -> + generator.writeObject(value.responseCustomToolCallInputDone) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid ResponsesServerEvent") + } + } + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/vectorstores/filebatches/FileBatchCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/vectorstores/filebatches/FileBatchCreateParams.kt index 50d84fa0d..ca03a868d 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/vectorstores/filebatches/FileBatchCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/vectorstores/filebatches/FileBatchCreateParams.kt @@ -60,8 +60,8 @@ private constructor( /** * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector * store should use. Useful for tools like `file_search` that can access files. If `attributes` - * or `chunking_strategy` are provided, they will be applied to all files in the batch. Mutually - * exclusive with `files`. + * or `chunking_strategy` are provided, they will be applied to all files in the batch. The + * maximum batch size is 2000 files. Mutually exclusive with `files`. * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -72,7 +72,7 @@ private constructor( * A list of objects that each include a `file_id` plus optional `attributes` or * `chunking_strategy`. Use this when you need to override metadata for specific files. The * global `attributes` or `chunking_strategy` will be ignored and must be specified for each - * file. Mutually exclusive with `file_ids`. + * file. The maximum batch size is 2000 files. Mutually exclusive with `file_ids`. * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -228,7 +228,7 @@ private constructor( * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. If * `attributes` or `chunking_strategy` are provided, they will be applied to all files in - * the batch. Mutually exclusive with `files`. + * the batch. The maximum batch size is 2000 files. Mutually exclusive with `files`. */ fun fileIds(fileIds: List) = apply { body.fileIds(fileIds) } @@ -252,7 +252,7 @@ private constructor( * A list of objects that each include a `file_id` plus optional `attributes` or * `chunking_strategy`. Use this when you need to override metadata for specific files. The * global `attributes` or `chunking_strategy` will be ignored and must be specified for each - * file. Mutually exclusive with `file_ids`. + * file. The maximum batch size is 2000 files. Mutually exclusive with `file_ids`. */ fun files(files: List) = apply { body.files(files) } @@ -465,7 +465,7 @@ private constructor( * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. If * `attributes` or `chunking_strategy` are provided, they will be applied to all files in - * the batch. Mutually exclusive with `files`. + * the batch. The maximum batch size is 2000 files. Mutually exclusive with `files`. * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -476,7 +476,7 @@ private constructor( * A list of objects that each include a `file_id` plus optional `attributes` or * `chunking_strategy`. Use this when you need to override metadata for specific files. The * global `attributes` or `chunking_strategy` will be ignored and must be specified for each - * file. Mutually exclusive with `file_ids`. + * file. The maximum batch size is 2000 files. Mutually exclusive with `file_ids`. * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -623,7 +623,8 @@ private constructor( * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. * If `attributes` or `chunking_strategy` are provided, they will be applied to all - * files in the batch. Mutually exclusive with `files`. + * files in the batch. The maximum batch size is 2000 files. Mutually exclusive with + * `files`. */ fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) @@ -654,7 +655,8 @@ private constructor( * A list of objects that each include a `file_id` plus optional `attributes` or * `chunking_strategy`. Use this when you need to override metadata for specific files. * The global `attributes` or `chunking_strategy` will be ignored and must be specified - * for each file. Mutually exclusive with `file_ids`. + * for each file. The maximum batch size is 2000 files. Mutually exclusive with + * `file_ids`. */ fun files(files: List) = files(JsonField.of(files)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/CompletionServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/CompletionServiceAsyncImpl.kt index 6ee85dcce..a46f0789e 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/CompletionServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/CompletionServiceAsyncImpl.kt @@ -112,6 +112,7 @@ class CompletionServiceAsyncImpl internal constructor(private val clientOptions: .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("completions") + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/FileServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/FileServiceAsyncImpl.kt index 34a348b4c..5a5501bcb 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/FileServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/FileServiceAsyncImpl.kt @@ -238,6 +238,7 @@ class FileServiceAsyncImpl internal constructor(private val clientOptions: Clien .method(HttpMethod.GET) .baseUrl(clientOptions.baseUrl()) .addPathSegments("files", params._pathParam(0), "content") + .putHeader("Accept", "application/binary") .build() .prepareAsync(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/ImageServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/ImageServiceAsyncImpl.kt index cd4232b6c..e05e95bdc 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/ImageServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/ImageServiceAsyncImpl.kt @@ -173,6 +173,7 @@ class ImageServiceAsyncImpl internal constructor(private val clientOptions: Clie .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("images", "edits") + .putHeader("Accept", "text/event-stream") .body( multipartFormData( clientOptions.jsonMapper, @@ -242,6 +243,7 @@ class ImageServiceAsyncImpl internal constructor(private val clientOptions: Clie .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("images", "generations") + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/ResponseServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/ResponseServiceAsyncImpl.kt index 92f701094..be955ada1 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/ResponseServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/ResponseServiceAsyncImpl.kt @@ -187,6 +187,7 @@ class ResponseServiceAsyncImpl internal constructor(private val clientOptions: C .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("responses") + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, @@ -266,6 +267,7 @@ class ResponseServiceAsyncImpl internal constructor(private val clientOptions: C .baseUrl(clientOptions.baseUrl()) .addPathSegments("responses", params._pathParam(0)) .putQueryParam("stream", "true") + .putHeader("Accept", "text/event-stream") .build() .prepareAsync(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/VideoServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/VideoServiceAsyncImpl.kt index c1d760ea7..0de010e0a 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/VideoServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/VideoServiceAsyncImpl.kt @@ -244,6 +244,7 @@ class VideoServiceAsyncImpl internal constructor(private val clientOptions: Clie .method(HttpMethod.GET) .baseUrl(clientOptions.baseUrl()) .addPathSegments("videos", params._pathParam(0), "content") + .putHeader("Accept", "application/binary") .build() .prepareAsync(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/audio/SpeechServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/audio/SpeechServiceAsyncImpl.kt index 200f2c848..9804b8f44 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/audio/SpeechServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/audio/SpeechServiceAsyncImpl.kt @@ -57,6 +57,7 @@ class SpeechServiceAsyncImpl internal constructor(private val clientOptions: Cli .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("audio", "speech") + .putHeader("Accept", "application/octet-stream") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepareAsync(clientOptions, params) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt index c89b2cf92..2aef63b3a 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt @@ -130,6 +130,7 @@ class TranscriptionServiceAsyncImpl internal constructor(private val clientOptio .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("audio", "transcriptions") + .putHeader("Accept", "text/event-stream") .body( multipartFormData( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/beta/ThreadServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/beta/ThreadServiceAsyncImpl.kt index 7e04a3f77..df8637a3a 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/beta/ThreadServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/beta/ThreadServiceAsyncImpl.kt @@ -332,6 +332,7 @@ class ThreadServiceAsyncImpl internal constructor(private val clientOptions: Cli .baseUrl(clientOptions.baseUrl()) .addPathSegments("threads", "runs") .putAllHeaders(DEFAULT_HEADERS) + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/beta/threads/RunServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/beta/threads/RunServiceAsyncImpl.kt index c492d9457..73caa4969 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/beta/threads/RunServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/beta/threads/RunServiceAsyncImpl.kt @@ -207,6 +207,7 @@ class RunServiceAsyncImpl internal constructor(private val clientOptions: Client .baseUrl(clientOptions.baseUrl()) .addPathSegments("threads", params._pathParam(0), "runs") .putAllHeaders(DEFAULT_HEADERS) + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, @@ -457,6 +458,7 @@ class RunServiceAsyncImpl internal constructor(private val clientOptions: Client "submit_tool_outputs", ) .putAllHeaders(DEFAULT_HEADERS) + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/chat/ChatCompletionServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/chat/ChatCompletionServiceAsyncImpl.kt index 391be3b16..7c62e71bb 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/chat/ChatCompletionServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/chat/ChatCompletionServiceAsyncImpl.kt @@ -164,6 +164,7 @@ internal constructor(private val clientOptions: ClientOptions) : ChatCompletionS .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("chat", "completions") + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/containers/files/ContentServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/containers/files/ContentServiceAsyncImpl.kt index ec7ba5192..3079b908f 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/containers/files/ContentServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/containers/files/ContentServiceAsyncImpl.kt @@ -67,6 +67,7 @@ class ContentServiceAsyncImpl internal constructor(private val clientOptions: Cl params._pathParam(1), "content", ) + .putHeader("Accept", "application/binary") .build() .prepareAsync(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/skills/ContentServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/skills/ContentServiceAsyncImpl.kt index c737c0e05..aba50b7ac 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/skills/ContentServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/skills/ContentServiceAsyncImpl.kt @@ -61,6 +61,7 @@ class ContentServiceAsyncImpl internal constructor(private val clientOptions: Cl .method(HttpMethod.GET) .baseUrl(clientOptions.baseUrl()) .addPathSegments("skills", params._pathParam(0), "content") + .putHeader("Accept", "application/binary") .build() .prepareAsync(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/skills/versions/ContentServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/skills/versions/ContentServiceAsyncImpl.kt index 09314b20e..be7df9f99 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/skills/versions/ContentServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/skills/versions/ContentServiceAsyncImpl.kt @@ -67,6 +67,7 @@ class ContentServiceAsyncImpl internal constructor(private val clientOptions: Cl params._pathParam(1), "content", ) + .putHeader("Accept", "application/binary") .build() .prepareAsync(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/CompletionServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/CompletionServiceImpl.kt index 9cbc00d7c..ecb25941c 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/CompletionServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/CompletionServiceImpl.kt @@ -103,6 +103,7 @@ class CompletionServiceImpl internal constructor(private val clientOptions: Clie .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("completions") + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/FileServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/FileServiceImpl.kt index 89ebb73a0..ab18410b2 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/FileServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/FileServiceImpl.kt @@ -208,6 +208,7 @@ class FileServiceImpl internal constructor(private val clientOptions: ClientOpti .method(HttpMethod.GET) .baseUrl(clientOptions.baseUrl()) .addPathSegments("files", params._pathParam(0), "content") + .putHeader("Accept", "application/binary") .build() .prepare(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/ImageServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/ImageServiceImpl.kt index ba4818dee..77d7fbbff 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/ImageServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/ImageServiceImpl.kt @@ -153,6 +153,7 @@ class ImageServiceImpl internal constructor(private val clientOptions: ClientOpt .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("images", "edits") + .putHeader("Accept", "text/event-stream") .body( multipartFormData( clientOptions.jsonMapper, @@ -216,6 +217,7 @@ class ImageServiceImpl internal constructor(private val clientOptions: ClientOpt .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("images", "generations") + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/ResponseServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/ResponseServiceImpl.kt index 3951d5705..5added9bd 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/ResponseServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/ResponseServiceImpl.kt @@ -163,6 +163,7 @@ class ResponseServiceImpl internal constructor(private val clientOptions: Client .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("responses") + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, @@ -236,6 +237,7 @@ class ResponseServiceImpl internal constructor(private val clientOptions: Client .baseUrl(clientOptions.baseUrl()) .addPathSegments("responses", params._pathParam(0)) .putQueryParam("stream", "true") + .putHeader("Accept", "text/event-stream") .build() .prepare(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/VideoServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/VideoServiceImpl.kt index fa9584942..5650b17e9 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/VideoServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/VideoServiceImpl.kt @@ -218,6 +218,7 @@ class VideoServiceImpl internal constructor(private val clientOptions: ClientOpt .method(HttpMethod.GET) .baseUrl(clientOptions.baseUrl()) .addPathSegments("videos", params._pathParam(0), "content") + .putHeader("Accept", "application/binary") .build() .prepare(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/SpeechServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/SpeechServiceImpl.kt index 4b461e0d7..12f839b46 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/SpeechServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/SpeechServiceImpl.kt @@ -53,6 +53,7 @@ class SpeechServiceImpl internal constructor(private val clientOptions: ClientOp .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("audio", "speech") + .putHeader("Accept", "application/octet-stream") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepare(clientOptions, params) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt index 065dfbbb2..0c48cc1e5 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt @@ -120,6 +120,7 @@ class TranscriptionServiceImpl internal constructor(private val clientOptions: C .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("audio", "transcriptions") + .putHeader("Accept", "text/event-stream") .body( multipartFormData( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/beta/ThreadServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/beta/ThreadServiceImpl.kt index d2d0688ed..93ee9ace7 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/beta/ThreadServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/beta/ThreadServiceImpl.kt @@ -299,6 +299,7 @@ class ThreadServiceImpl internal constructor(private val clientOptions: ClientOp .baseUrl(clientOptions.baseUrl()) .addPathSegments("threads", "runs") .putAllHeaders(DEFAULT_HEADERS) + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/beta/threads/RunServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/beta/threads/RunServiceImpl.kt index b914ed820..c5519171f 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/beta/threads/RunServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/beta/threads/RunServiceImpl.kt @@ -179,6 +179,7 @@ class RunServiceImpl internal constructor(private val clientOptions: ClientOptio .baseUrl(clientOptions.baseUrl()) .addPathSegments("threads", params._pathParam(0), "runs") .putAllHeaders(DEFAULT_HEADERS) + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, @@ -410,6 +411,7 @@ class RunServiceImpl internal constructor(private val clientOptions: ClientOptio "submit_tool_outputs", ) .putAllHeaders(DEFAULT_HEADERS) + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/chat/ChatCompletionServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/chat/ChatCompletionServiceImpl.kt index 9cdc6db9a..3ba4901f0 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/chat/ChatCompletionServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/chat/ChatCompletionServiceImpl.kt @@ -153,6 +153,7 @@ class ChatCompletionServiceImpl internal constructor(private val clientOptions: .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("chat", "completions") + .putHeader("Accept", "text/event-stream") .body( json( clientOptions.jsonMapper, diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/containers/files/ContentServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/containers/files/ContentServiceImpl.kt index d0b1cdb8d..9423bd9be 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/containers/files/ContentServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/containers/files/ContentServiceImpl.kt @@ -66,6 +66,7 @@ class ContentServiceImpl internal constructor(private val clientOptions: ClientO params._pathParam(1), "content", ) + .putHeader("Accept", "application/binary") .build() .prepare(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/skills/ContentServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/skills/ContentServiceImpl.kt index 88b12109c..b4ac8443c 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/skills/ContentServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/skills/ContentServiceImpl.kt @@ -60,6 +60,7 @@ class ContentServiceImpl internal constructor(private val clientOptions: ClientO .method(HttpMethod.GET) .baseUrl(clientOptions.baseUrl()) .addPathSegments("skills", params._pathParam(0), "content") + .putHeader("Accept", "application/binary") .build() .prepare(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/skills/versions/ContentServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/skills/versions/ContentServiceImpl.kt index 53f61d930..dfb857f5c 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/skills/versions/ContentServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/skills/versions/ContentServiceImpl.kt @@ -66,6 +66,7 @@ class ContentServiceImpl internal constructor(private val clientOptions: ClientO params._pathParam(1), "content", ) + .putHeader("Accept", "application/binary") .build() .prepare(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/openai-java-core/src/test/kotlin/com/openai/core/http/HttpRequestBodiesTest.kt b/openai-java-core/src/test/kotlin/com/openai/core/http/HttpRequestBodiesTest.kt new file mode 100644 index 000000000..e4281b24b --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/core/http/HttpRequestBodiesTest.kt @@ -0,0 +1,739 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.core.http + +import com.openai.core.MultipartField +import com.openai.core.jsonMapper +import java.io.ByteArrayOutputStream +import java.io.InputStream +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class HttpRequestBodiesTest { + + @Test + fun multipartFormData_serializesFieldWithFilename() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "file" to + MultipartField.builder() + .value("hello") + .filename("hello.txt") + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(output.size().toLong()).isEqualTo(body.contentLength()) + val boundary = body.contentType()!!.substringAfter("multipart/form-data; boundary=") + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="file"; filename="hello.txt" + |Content-Type: text/plain + | + |hello + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesFieldWithoutFilename() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "field" to + MultipartField.builder() + .value("value") + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(output.size().toLong()).isEqualTo(body.contentLength()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="field" + |Content-Type: text/plain + | + |value + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesInputStream() { + // Use `.buffered()` to get a non-ByteArrayInputStream, which hits the non-repeatable code + // path. + val inputStream = "stream content".byteInputStream().buffered() + val body = + multipartFormData( + jsonMapper(), + mapOf( + "data" to + MultipartField.builder() + .value(inputStream) + .contentType("application/octet-stream") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isFalse() + assertThat(body.contentLength()).isEqualTo(-1L) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="data" + |Content-Type: application/octet-stream + | + |stream content + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesByteArray() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "binary" to + MultipartField.builder() + .value("abc".toByteArray()) + .contentType("application/octet-stream") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="binary" + |Content-Type: application/octet-stream + | + |abc + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesBooleanValue() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "flag" to + MultipartField.builder() + .value(true) + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="flag" + |Content-Type: text/plain + | + |true + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesNumberValue() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "count" to + MultipartField.builder().value(42).contentType("text/plain").build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="count" + |Content-Type: text/plain + | + |42 + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesNullValueAsNoParts() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "present" to + MultipartField.builder() + .value("yes") + .contentType("text/plain") + .build(), + "absent" to + MultipartField.builder() + .value(null as String?) + .contentType("text/plain") + .build(), + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="present" + |Content-Type: text/plain + | + |yes + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesArray() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "items" to + MultipartField.builder>() + .value(listOf("alpha", "beta", "gamma")) + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="items[]" + |Content-Type: text/plain + | + |alpha + |--$boundary + |Content-Disposition: form-data; name="items[]" + |Content-Type: text/plain + | + |beta + |--$boundary + |Content-Disposition: form-data; name="items[]" + |Content-Type: text/plain + | + |gamma + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesObjectAsNestedParts() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "meta" to + MultipartField.builder>() + .value(mapOf("key1" to "val1", "key2" to "val2")) + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="meta[key1]" + |Content-Type: text/plain + | + |val1 + |--$boundary + |Content-Disposition: form-data; name="meta[key2]" + |Content-Type: text/plain + | + |val2 + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesMultipleFields() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "name" to + MultipartField.builder() + .value("Alice") + .contentType("text/plain") + .build(), + "age" to + MultipartField.builder().value(30).contentType("text/plain").build(), + "file" to + MultipartField.builder() + .value("file contents") + .filename("doc.txt") + .contentType("text/plain") + .build(), + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="name" + |Content-Type: text/plain + | + |Alice + |--$boundary + |Content-Disposition: form-data; name="age" + |Content-Type: text/plain + | + |30 + |--$boundary + |Content-Disposition: form-data; name="file"; filename="doc.txt" + |Content-Type: text/plain + | + |file contents + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_quotesSpecialCharactersInNameAndFilename() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "field\nname" to + MultipartField.builder() + .value("value") + .filename("file\r\"name.txt") + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="field%0Aname"; filename="file%0D%22name.txt" + |Content-Type: text/plain + | + |value + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_writeIsRepeatable() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "field" to + MultipartField.builder() + .value("repeatable") + .contentType("text/plain") + .build() + ), + ) + + val output1 = ByteArrayOutputStream() + body.writeTo(output1) + val output2 = ByteArrayOutputStream() + body.writeTo(output2) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output1.size().toLong()) + val boundary = boundary(body) + val expected = + """ + |--$boundary + |Content-Disposition: form-data; name="field" + |Content-Type: text/plain + | + |repeatable + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + assertThat(output1.toString("UTF-8")).isEqualTo(expected) + assertThat(output2.toString("UTF-8")).isEqualTo(expected) + } + + @Test + fun multipartFormData_serializesByteArrayInputStream() { + // ByteArrayInputStream is specifically handled as repeatable with known content length. + val inputStream = "byte array stream".byteInputStream() + val body = + multipartFormData( + jsonMapper(), + mapOf( + "data" to + MultipartField.builder() + .value(inputStream) + .contentType("application/octet-stream") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="data" + |Content-Type: application/octet-stream + | + |byte array stream + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesInputStreamWithFilename() { + // Use `.buffered()` to get a non-ByteArrayInputStream, which hits the non-repeatable code + // path. + val inputStream = "file data".byteInputStream().buffered() + val body = + multipartFormData( + jsonMapper(), + mapOf( + "upload" to + MultipartField.builder() + .value(inputStream) + .filename("upload.bin") + .contentType("application/octet-stream") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isFalse() + assertThat(body.contentLength()).isEqualTo(-1L) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="upload"; filename="upload.bin" + |Content-Type: application/octet-stream + | + |file data + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesNestedArrayInObject() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "data" to + MultipartField.builder>>() + .value(mapOf("tags" to listOf("a", "b"))) + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="data[tags][]" + |Content-Type: text/plain + | + |a + |--$boundary + |Content-Disposition: form-data; name="data[tags][]" + |Content-Type: text/plain + | + |b + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_contentLengthIsUnknownWhenInputStreamPresent() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "text" to + MultipartField.builder() + .value("hello") + .contentType("text/plain") + .build(), + "stream" to + MultipartField.builder() + // Use `.buffered()` to get a non-ByteArrayInputStream, which hits the + // non-repeatable code path. + .value("data".byteInputStream().buffered()) + .contentType("application/octet-stream") + .build(), + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isFalse() + assertThat(body.contentLength()).isEqualTo(-1L) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="text" + |Content-Type: text/plain + | + |hello + |--$boundary + |Content-Disposition: form-data; name="stream" + |Content-Type: application/octet-stream + | + |data + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesEmptyArray() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "required" to + MultipartField.builder() + .value("present") + .contentType("text/plain") + .build(), + "items" to + MultipartField.builder>() + .value(emptyList()) + .contentType("text/plain") + .build(), + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="required" + |Content-Type: text/plain + | + |present + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesEmptyObject() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "required" to + MultipartField.builder() + .value("present") + .contentType("text/plain") + .build(), + "meta" to + MultipartField.builder>() + .value(emptyMap()) + .contentType("text/plain") + .build(), + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="required" + |Content-Type: text/plain + | + |present + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + private fun boundary(body: HttpRequestBody): String = + body.contentType()!!.substringAfter("multipart/form-data; boundary=") +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponsesClientEventTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponsesClientEventTest.kt new file mode 100644 index 000000000..bf6e59a4e --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponsesClientEventTest.kt @@ -0,0 +1,271 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.responses + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.JsonValue +import com.openai.core.jsonMapper +import com.openai.models.ChatModel +import com.openai.models.Reasoning +import com.openai.models.ReasoningEffort +import com.openai.models.ResponseFormatText +import com.openai.models.ResponsesModel +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ResponsesClientEventTest { + + @Test + fun create() { + val responsesClientEvent = + ResponsesClientEvent.builder() + .background(true) + .addContextManagement( + ResponsesClientEvent.ContextManagement.builder() + .type("type") + .compactThreshold(1000L) + .build() + ) + .conversation("string") + .addInclude(ResponseIncludable.FILE_SEARCH_CALL_RESULTS) + .input("string") + .instructions("instructions") + .maxOutputTokens(0L) + .maxToolCalls(0L) + .metadata( + ResponsesClientEvent.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .parallelToolCalls(true) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(ResponsesClientEvent.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(ResponsesClientEvent.ServiceTier.AUTO) + .store(true) + .stream(true) + .streamOptions( + ResponsesClientEvent.StreamOptions.builder().includeObfuscation(true).build() + ) + .temperature(1.0) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topLogprobs(0L) + .topP(1.0) + .truncation(ResponsesClientEvent.Truncation.AUTO) + .user("user-1234") + .build() + + assertThat(responsesClientEvent.background()).contains(true) + assertThat(responsesClientEvent.contextManagement().getOrNull()) + .containsExactly( + ResponsesClientEvent.ContextManagement.builder() + .type("type") + .compactThreshold(1000L) + .build() + ) + assertThat(responsesClientEvent.conversation()) + .contains(ResponsesClientEvent.Conversation.ofId("string")) + assertThat(responsesClientEvent.include().getOrNull()) + .containsExactly(ResponseIncludable.FILE_SEARCH_CALL_RESULTS) + assertThat(responsesClientEvent.input()) + .contains(ResponsesClientEvent.Input.ofText("string")) + assertThat(responsesClientEvent.instructions()).contains("instructions") + assertThat(responsesClientEvent.maxOutputTokens()).contains(0L) + assertThat(responsesClientEvent.maxToolCalls()).contains(0L) + assertThat(responsesClientEvent.metadata()) + .contains( + ResponsesClientEvent.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + assertThat(responsesClientEvent.model()).contains(ResponsesModel.ofChat(ChatModel.GPT_5_1)) + assertThat(responsesClientEvent.parallelToolCalls()).contains(true) + assertThat(responsesClientEvent.previousResponseId()).contains("previous_response_id") + assertThat(responsesClientEvent.prompt()) + .contains( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + assertThat(responsesClientEvent.promptCacheKey()).contains("prompt-cache-key-1234") + assertThat(responsesClientEvent.promptCacheRetention()) + .contains(ResponsesClientEvent.PromptCacheRetention.IN_MEMORY) + assertThat(responsesClientEvent.reasoning()) + .contains( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + assertThat(responsesClientEvent.safetyIdentifier()).contains("safety-identifier-1234") + assertThat(responsesClientEvent.serviceTier()) + .contains(ResponsesClientEvent.ServiceTier.AUTO) + assertThat(responsesClientEvent.store()).contains(true) + assertThat(responsesClientEvent.stream()).contains(true) + assertThat(responsesClientEvent.streamOptions()) + .contains(ResponsesClientEvent.StreamOptions.builder().includeObfuscation(true).build()) + assertThat(responsesClientEvent.temperature()).contains(1.0) + assertThat(responsesClientEvent.text()) + .contains( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + assertThat(responsesClientEvent.toolChoice()) + .contains(ResponsesClientEvent.ToolChoice.ofOptions(ToolChoiceOptions.NONE)) + assertThat(responsesClientEvent.tools().getOrNull()) + .containsExactly( + Tool.ofFunction( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + ) + assertThat(responsesClientEvent.topLogprobs()).contains(0L) + assertThat(responsesClientEvent.topP()).contains(1.0) + assertThat(responsesClientEvent.truncation()).contains(ResponsesClientEvent.Truncation.AUTO) + assertThat(responsesClientEvent.user()).contains("user-1234") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val responsesClientEvent = + ResponsesClientEvent.builder() + .background(true) + .addContextManagement( + ResponsesClientEvent.ContextManagement.builder() + .type("type") + .compactThreshold(1000L) + .build() + ) + .conversation("string") + .addInclude(ResponseIncludable.FILE_SEARCH_CALL_RESULTS) + .input("string") + .instructions("instructions") + .maxOutputTokens(0L) + .maxToolCalls(0L) + .metadata( + ResponsesClientEvent.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .parallelToolCalls(true) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(ResponsesClientEvent.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(ResponsesClientEvent.ServiceTier.AUTO) + .store(true) + .stream(true) + .streamOptions( + ResponsesClientEvent.StreamOptions.builder().includeObfuscation(true).build() + ) + .temperature(1.0) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topLogprobs(0L) + .topP(1.0) + .truncation(ResponsesClientEvent.Truncation.AUTO) + .user("user-1234") + .build() + + val roundtrippedResponsesClientEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesClientEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesClientEvent).isEqualTo(responsesClientEvent) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponsesServerEventTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponsesServerEventTest.kt new file mode 100644 index 000000000..7371badda --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponsesServerEventTest.kt @@ -0,0 +1,6591 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.responses + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.JsonValue +import com.openai.core.jsonMapper +import com.openai.errors.OpenAIInvalidDataException +import com.openai.models.ChatModel +import com.openai.models.Reasoning +import com.openai.models.ReasoningEffort +import com.openai.models.ResponseFormatText +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class ResponsesServerEventTest { + + @Test + fun ofResponseAudioDelta() { + val responseAudioDelta = + ResponseAudioDeltaEvent.builder().delta("delta").sequenceNumber(0L).build() + + val responsesServerEvent = ResponsesServerEvent.ofResponseAudioDelta(responseAudioDelta) + + assertThat(responsesServerEvent.responseAudioDelta()).contains(responseAudioDelta) + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseAudioDeltaRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseAudioDelta( + ResponseAudioDeltaEvent.builder().delta("delta").sequenceNumber(0L).build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseAudioDone() { + val responseAudioDone = ResponseAudioDoneEvent.builder().sequenceNumber(0L).build() + + val responsesServerEvent = ResponsesServerEvent.ofResponseAudioDone(responseAudioDone) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).contains(responseAudioDone) + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseAudioDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseAudioDone( + ResponseAudioDoneEvent.builder().sequenceNumber(0L).build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseAudioTranscriptDelta() { + val responseAudioTranscriptDelta = + ResponseAudioTranscriptDeltaEvent.builder().delta("delta").sequenceNumber(0L).build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseAudioTranscriptDelta(responseAudioTranscriptDelta) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()) + .contains(responseAudioTranscriptDelta) + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseAudioTranscriptDeltaRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseAudioTranscriptDelta( + ResponseAudioTranscriptDeltaEvent.builder() + .delta("delta") + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseAudioTranscriptDone() { + val responseAudioTranscriptDone = + ResponseAudioTranscriptDoneEvent.builder().sequenceNumber(0L).build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseAudioTranscriptDone(responseAudioTranscriptDone) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()) + .contains(responseAudioTranscriptDone) + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseAudioTranscriptDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseAudioTranscriptDone( + ResponseAudioTranscriptDoneEvent.builder().sequenceNumber(0L).build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseCodeInterpreterCallCodeDelta() { + val responseCodeInterpreterCallCodeDelta = + ResponseCodeInterpreterCallCodeDeltaEvent.builder() + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseCodeInterpreterCallCodeDelta( + responseCodeInterpreterCallCodeDelta + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()) + .contains(responseCodeInterpreterCallCodeDelta) + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseCodeInterpreterCallCodeDeltaRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseCodeInterpreterCallCodeDelta( + ResponseCodeInterpreterCallCodeDeltaEvent.builder() + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseCodeInterpreterCallCodeDone() { + val responseCodeInterpreterCallCodeDone = + ResponseCodeInterpreterCallCodeDoneEvent.builder() + .code("code") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseCodeInterpreterCallCodeDone( + responseCodeInterpreterCallCodeDone + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()) + .contains(responseCodeInterpreterCallCodeDone) + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseCodeInterpreterCallCodeDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseCodeInterpreterCallCodeDone( + ResponseCodeInterpreterCallCodeDoneEvent.builder() + .code("code") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseCodeInterpreterCallCompleted() { + val responseCodeInterpreterCallCompleted = + ResponseCodeInterpreterCallCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseCodeInterpreterCallCompleted( + responseCodeInterpreterCallCompleted + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()) + .contains(responseCodeInterpreterCallCompleted) + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseCodeInterpreterCallCompletedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseCodeInterpreterCallCompleted( + ResponseCodeInterpreterCallCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseCodeInterpreterCallInProgress() { + val responseCodeInterpreterCallInProgress = + ResponseCodeInterpreterCallInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseCodeInterpreterCallInProgress( + responseCodeInterpreterCallInProgress + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()) + .contains(responseCodeInterpreterCallInProgress) + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseCodeInterpreterCallInProgressRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseCodeInterpreterCallInProgress( + ResponseCodeInterpreterCallInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseCodeInterpreterCallInterpreting() { + val responseCodeInterpreterCallInterpreting = + ResponseCodeInterpreterCallInterpretingEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseCodeInterpreterCallInterpreting( + responseCodeInterpreterCallInterpreting + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()) + .contains(responseCodeInterpreterCallInterpreting) + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseCodeInterpreterCallInterpretingRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseCodeInterpreterCallInterpreting( + ResponseCodeInterpreterCallInterpretingEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseCompleted() { + val responseCompleted = + ResponseCompletedEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = ResponsesServerEvent.ofResponseCompleted(responseCompleted) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).contains(responseCompleted) + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseCompletedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseCompleted( + ResponseCompletedEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob + .builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseContentPartAdded() { + val responseContentPartAdded = + ResponseContentPartAddedEvent.builder() + .contentIndex(0L) + .itemId("item_id") + .outputIndex(0L) + .part( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseContentPartAdded(responseContentPartAdded) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()) + .contains(responseContentPartAdded) + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseContentPartAddedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseContentPartAdded( + ResponseContentPartAddedEvent.builder() + .contentIndex(0L) + .itemId("item_id") + .outputIndex(0L) + .part( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseContentPartDone() { + val responseContentPartDone = + ResponseContentPartDoneEvent.builder() + .contentIndex(0L) + .itemId("item_id") + .outputIndex(0L) + .part( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseContentPartDone(responseContentPartDone) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).contains(responseContentPartDone) + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseContentPartDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseContentPartDone( + ResponseContentPartDoneEvent.builder() + .contentIndex(0L) + .itemId("item_id") + .outputIndex(0L) + .part( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseCreated() { + val responseCreated = + ResponseCreatedEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = ResponsesServerEvent.ofResponseCreated(responseCreated) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).contains(responseCreated) + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseCreatedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseCreated( + ResponseCreatedEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob + .builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofError() { + val error = + ResponseErrorEvent.builder() + .code("code") + .message("message") + .param("param") + .sequenceNumber(0L) + .build() + + val responsesServerEvent = ResponsesServerEvent.ofError(error) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).contains(error) + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofErrorRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofError( + ResponseErrorEvent.builder() + .code("code") + .message("message") + .param("param") + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseFileSearchCallCompleted() { + val responseFileSearchCallCompleted = + ResponseFileSearchCallCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseFileSearchCallCompleted(responseFileSearchCallCompleted) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()) + .contains(responseFileSearchCallCompleted) + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseFileSearchCallCompletedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseFileSearchCallCompleted( + ResponseFileSearchCallCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseFileSearchCallInProgress() { + val responseFileSearchCallInProgress = + ResponseFileSearchCallInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseFileSearchCallInProgress( + responseFileSearchCallInProgress + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()) + .contains(responseFileSearchCallInProgress) + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseFileSearchCallInProgressRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseFileSearchCallInProgress( + ResponseFileSearchCallInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseFileSearchCallSearching() { + val responseFileSearchCallSearching = + ResponseFileSearchCallSearchingEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseFileSearchCallSearching(responseFileSearchCallSearching) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()) + .contains(responseFileSearchCallSearching) + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseFileSearchCallSearchingRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseFileSearchCallSearching( + ResponseFileSearchCallSearchingEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseFunctionCallArgumentsDelta() { + val responseFunctionCallArgumentsDelta = + ResponseFunctionCallArgumentsDeltaEvent.builder() + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseFunctionCallArgumentsDelta( + responseFunctionCallArgumentsDelta + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()) + .contains(responseFunctionCallArgumentsDelta) + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseFunctionCallArgumentsDeltaRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseFunctionCallArgumentsDelta( + ResponseFunctionCallArgumentsDeltaEvent.builder() + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseFunctionCallArgumentsDone() { + val responseFunctionCallArgumentsDone = + ResponseFunctionCallArgumentsDoneEvent.builder() + .arguments("arguments") + .itemId("item_id") + .name("name") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseFunctionCallArgumentsDone( + responseFunctionCallArgumentsDone + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()) + .contains(responseFunctionCallArgumentsDone) + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseFunctionCallArgumentsDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseFunctionCallArgumentsDone( + ResponseFunctionCallArgumentsDoneEvent.builder() + .arguments("arguments") + .itemId("item_id") + .name("name") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseInProgress() { + val responseInProgress = + ResponseInProgressEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = ResponsesServerEvent.ofResponseInProgress(responseInProgress) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).contains(responseInProgress) + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseInProgressRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseInProgress( + ResponseInProgressEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob + .builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseFailed() { + val responseFailed = + ResponseFailedEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = ResponsesServerEvent.ofResponseFailed(responseFailed) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).contains(responseFailed) + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseFailedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseFailed( + ResponseFailedEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob + .builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseIncomplete() { + val responseIncomplete = + ResponseIncompleteEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = ResponsesServerEvent.ofResponseIncomplete(responseIncomplete) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).contains(responseIncomplete) + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseIncompleteRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseIncomplete( + ResponseIncompleteEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob + .builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseOutputItemAdded() { + val responseOutputItemAdded = + ResponseOutputItemAddedEvent.builder() + .item( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseOutputItemAdded(responseOutputItemAdded) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).contains(responseOutputItemAdded) + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseOutputItemAddedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseOutputItemAdded( + ResponseOutputItemAddedEvent.builder() + .item( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseOutputItemDone() { + val responseOutputItemDone = + ResponseOutputItemDoneEvent.builder() + .item( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseOutputItemDone(responseOutputItemDone) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).contains(responseOutputItemDone) + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseOutputItemDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseOutputItemDone( + ResponseOutputItemDoneEvent.builder() + .item( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseReasoningSummaryPartAdded() { + val responseReasoningSummaryPartAdded = + ResponseReasoningSummaryPartAddedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .part(ResponseReasoningSummaryPartAddedEvent.Part.builder().text("text").build()) + .sequenceNumber(0L) + .summaryIndex(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningSummaryPartAdded( + responseReasoningSummaryPartAdded + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()) + .contains(responseReasoningSummaryPartAdded) + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseReasoningSummaryPartAddedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningSummaryPartAdded( + ResponseReasoningSummaryPartAddedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .part( + ResponseReasoningSummaryPartAddedEvent.Part.builder().text("text").build() + ) + .sequenceNumber(0L) + .summaryIndex(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseReasoningSummaryPartDone() { + val responseReasoningSummaryPartDone = + ResponseReasoningSummaryPartDoneEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .part(ResponseReasoningSummaryPartDoneEvent.Part.builder().text("text").build()) + .sequenceNumber(0L) + .summaryIndex(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningSummaryPartDone( + responseReasoningSummaryPartDone + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()) + .contains(responseReasoningSummaryPartDone) + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseReasoningSummaryPartDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningSummaryPartDone( + ResponseReasoningSummaryPartDoneEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .part(ResponseReasoningSummaryPartDoneEvent.Part.builder().text("text").build()) + .sequenceNumber(0L) + .summaryIndex(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseReasoningSummaryTextDelta() { + val responseReasoningSummaryTextDelta = + ResponseReasoningSummaryTextDeltaEvent.builder() + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .summaryIndex(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningSummaryTextDelta( + responseReasoningSummaryTextDelta + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()) + .contains(responseReasoningSummaryTextDelta) + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseReasoningSummaryTextDeltaRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningSummaryTextDelta( + ResponseReasoningSummaryTextDeltaEvent.builder() + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .summaryIndex(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseReasoningSummaryTextDone() { + val responseReasoningSummaryTextDone = + ResponseReasoningSummaryTextDoneEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .summaryIndex(0L) + .text("text") + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningSummaryTextDone( + responseReasoningSummaryTextDone + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()) + .contains(responseReasoningSummaryTextDone) + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseReasoningSummaryTextDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningSummaryTextDone( + ResponseReasoningSummaryTextDoneEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .summaryIndex(0L) + .text("text") + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseReasoningTextDelta() { + val responseReasoningTextDelta = + ResponseReasoningTextDeltaEvent.builder() + .contentIndex(0L) + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningTextDelta(responseReasoningTextDelta) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()) + .contains(responseReasoningTextDelta) + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseReasoningTextDeltaRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningTextDelta( + ResponseReasoningTextDeltaEvent.builder() + .contentIndex(0L) + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseReasoningTextDone() { + val responseReasoningTextDone = + ResponseReasoningTextDoneEvent.builder() + .contentIndex(0L) + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .text("text") + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningTextDone(responseReasoningTextDone) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()) + .contains(responseReasoningTextDone) + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseReasoningTextDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseReasoningTextDone( + ResponseReasoningTextDoneEvent.builder() + .contentIndex(0L) + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .text("text") + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseRefusalDelta() { + val responseRefusalDelta = + ResponseRefusalDeltaEvent.builder() + .contentIndex(0L) + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = ResponsesServerEvent.ofResponseRefusalDelta(responseRefusalDelta) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).contains(responseRefusalDelta) + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseRefusalDeltaRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseRefusalDelta( + ResponseRefusalDeltaEvent.builder() + .contentIndex(0L) + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseRefusalDone() { + val responseRefusalDone = + ResponseRefusalDoneEvent.builder() + .contentIndex(0L) + .itemId("item_id") + .outputIndex(0L) + .refusal("refusal") + .sequenceNumber(0L) + .build() + + val responsesServerEvent = ResponsesServerEvent.ofResponseRefusalDone(responseRefusalDone) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).contains(responseRefusalDone) + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseRefusalDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseRefusalDone( + ResponseRefusalDoneEvent.builder() + .contentIndex(0L) + .itemId("item_id") + .outputIndex(0L) + .refusal("refusal") + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseOutputTextDelta() { + val responseOutputTextDelta = + ResponseTextDeltaEvent.builder() + .contentIndex(0L) + .delta("delta") + .itemId("item_id") + .addLogprob( + ResponseTextDeltaEvent.Logprob.builder() + .token("token") + .logprob(0.0) + .addTopLogprob( + ResponseTextDeltaEvent.Logprob.TopLogprob.builder() + .token("token") + .logprob(0.0) + .build() + ) + .build() + ) + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseOutputTextDelta(responseOutputTextDelta) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).contains(responseOutputTextDelta) + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseOutputTextDeltaRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseOutputTextDelta( + ResponseTextDeltaEvent.builder() + .contentIndex(0L) + .delta("delta") + .itemId("item_id") + .addLogprob( + ResponseTextDeltaEvent.Logprob.builder() + .token("token") + .logprob(0.0) + .addTopLogprob( + ResponseTextDeltaEvent.Logprob.TopLogprob.builder() + .token("token") + .logprob(0.0) + .build() + ) + .build() + ) + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseOutputTextDone() { + val responseOutputTextDone = + ResponseTextDoneEvent.builder() + .contentIndex(0L) + .itemId("item_id") + .addLogprob( + ResponseTextDoneEvent.Logprob.builder() + .token("token") + .logprob(0.0) + .addTopLogprob( + ResponseTextDoneEvent.Logprob.TopLogprob.builder() + .token("token") + .logprob(0.0) + .build() + ) + .build() + ) + .outputIndex(0L) + .sequenceNumber(0L) + .text("text") + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseOutputTextDone(responseOutputTextDone) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).contains(responseOutputTextDone) + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseOutputTextDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseOutputTextDone( + ResponseTextDoneEvent.builder() + .contentIndex(0L) + .itemId("item_id") + .addLogprob( + ResponseTextDoneEvent.Logprob.builder() + .token("token") + .logprob(0.0) + .addTopLogprob( + ResponseTextDoneEvent.Logprob.TopLogprob.builder() + .token("token") + .logprob(0.0) + .build() + ) + .build() + ) + .outputIndex(0L) + .sequenceNumber(0L) + .text("text") + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseWebSearchCallCompleted() { + val responseWebSearchCallCompleted = + ResponseWebSearchCallCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseWebSearchCallCompleted(responseWebSearchCallCompleted) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()) + .contains(responseWebSearchCallCompleted) + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseWebSearchCallCompletedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseWebSearchCallCompleted( + ResponseWebSearchCallCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseWebSearchCallInProgress() { + val responseWebSearchCallInProgress = + ResponseWebSearchCallInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseWebSearchCallInProgress(responseWebSearchCallInProgress) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()) + .contains(responseWebSearchCallInProgress) + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseWebSearchCallInProgressRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseWebSearchCallInProgress( + ResponseWebSearchCallInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseWebSearchCallSearching() { + val responseWebSearchCallSearching = + ResponseWebSearchCallSearchingEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseWebSearchCallSearching(responseWebSearchCallSearching) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()) + .contains(responseWebSearchCallSearching) + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseWebSearchCallSearchingRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseWebSearchCallSearching( + ResponseWebSearchCallSearchingEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseImageGenerationCallCompleted() { + val responseImageGenerationCallCompleted = + ResponseImageGenCallCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseImageGenerationCallCompleted( + responseImageGenerationCallCompleted + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()) + .contains(responseImageGenerationCallCompleted) + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseImageGenerationCallCompletedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseImageGenerationCallCompleted( + ResponseImageGenCallCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseImageGenerationCallGenerating() { + val responseImageGenerationCallGenerating = + ResponseImageGenCallGeneratingEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseImageGenerationCallGenerating( + responseImageGenerationCallGenerating + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()) + .contains(responseImageGenerationCallGenerating) + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseImageGenerationCallGeneratingRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseImageGenerationCallGenerating( + ResponseImageGenCallGeneratingEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseImageGenerationCallInProgress() { + val responseImageGenerationCallInProgress = + ResponseImageGenCallInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseImageGenerationCallInProgress( + responseImageGenerationCallInProgress + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()) + .contains(responseImageGenerationCallInProgress) + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseImageGenerationCallInProgressRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseImageGenerationCallInProgress( + ResponseImageGenCallInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseImageGenerationCallPartialImage() { + val responseImageGenerationCallPartialImage = + ResponseImageGenCallPartialImageEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .partialImageB64("partial_image_b64") + .partialImageIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseImageGenerationCallPartialImage( + responseImageGenerationCallPartialImage + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()) + .contains(responseImageGenerationCallPartialImage) + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseImageGenerationCallPartialImageRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseImageGenerationCallPartialImage( + ResponseImageGenCallPartialImageEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .partialImageB64("partial_image_b64") + .partialImageIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseMcpCallArgumentsDelta() { + val responseMcpCallArgumentsDelta = + ResponseMcpCallArgumentsDeltaEvent.builder() + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpCallArgumentsDelta(responseMcpCallArgumentsDelta) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()) + .contains(responseMcpCallArgumentsDelta) + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseMcpCallArgumentsDeltaRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpCallArgumentsDelta( + ResponseMcpCallArgumentsDeltaEvent.builder() + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseMcpCallArgumentsDone() { + val responseMcpCallArgumentsDone = + ResponseMcpCallArgumentsDoneEvent.builder() + .arguments("arguments") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpCallArgumentsDone(responseMcpCallArgumentsDone) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()) + .contains(responseMcpCallArgumentsDone) + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseMcpCallArgumentsDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpCallArgumentsDone( + ResponseMcpCallArgumentsDoneEvent.builder() + .arguments("arguments") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseMcpCallCompleted() { + val responseMcpCallCompleted = + ResponseMcpCallCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpCallCompleted(responseMcpCallCompleted) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()) + .contains(responseMcpCallCompleted) + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseMcpCallCompletedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpCallCompleted( + ResponseMcpCallCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseMcpCallFailed() { + val responseMcpCallFailed = + ResponseMcpCallFailedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpCallFailed(responseMcpCallFailed) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).contains(responseMcpCallFailed) + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseMcpCallFailedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpCallFailed( + ResponseMcpCallFailedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseMcpCallInProgress() { + val responseMcpCallInProgress = + ResponseMcpCallInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpCallInProgress(responseMcpCallInProgress) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()) + .contains(responseMcpCallInProgress) + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseMcpCallInProgressRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpCallInProgress( + ResponseMcpCallInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseMcpListToolsCompleted() { + val responseMcpListToolsCompleted = + ResponseMcpListToolsCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpListToolsCompleted(responseMcpListToolsCompleted) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()) + .contains(responseMcpListToolsCompleted) + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseMcpListToolsCompletedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpListToolsCompleted( + ResponseMcpListToolsCompletedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseMcpListToolsFailed() { + val responseMcpListToolsFailed = + ResponseMcpListToolsFailedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpListToolsFailed(responseMcpListToolsFailed) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()) + .contains(responseMcpListToolsFailed) + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseMcpListToolsFailedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpListToolsFailed( + ResponseMcpListToolsFailedEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseMcpListToolsInProgress() { + val responseMcpListToolsInProgress = + ResponseMcpListToolsInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpListToolsInProgress(responseMcpListToolsInProgress) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()) + .contains(responseMcpListToolsInProgress) + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseMcpListToolsInProgressRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseMcpListToolsInProgress( + ResponseMcpListToolsInProgressEvent.builder() + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseOutputTextAnnotationAdded() { + val responseOutputTextAnnotationAdded = + ResponseOutputTextAnnotationAddedEvent.builder() + .annotation(JsonValue.from(mapOf())) + .annotationIndex(0L) + .contentIndex(0L) + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseOutputTextAnnotationAdded( + responseOutputTextAnnotationAdded + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()) + .contains(responseOutputTextAnnotationAdded) + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseOutputTextAnnotationAddedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseOutputTextAnnotationAdded( + ResponseOutputTextAnnotationAddedEvent.builder() + .annotation(JsonValue.from(mapOf())) + .annotationIndex(0L) + .contentIndex(0L) + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseQueued() { + val responseQueued = + ResponseQueuedEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = ResponsesServerEvent.ofResponseQueued(responseQueued) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).contains(responseQueued) + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseQueuedRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseQueued( + ResponseQueuedEvent.builder() + .response( + Response.builder() + .id("id") + .createdAt(0.0) + .error( + ResponseError.builder() + .code(ResponseError.Code.SERVER_ERROR) + .message("message") + .build() + ) + .incompleteDetails( + Response.IncompleteDetails.builder() + .reason(Response.IncompleteDetails.Reason.MAX_OUTPUT_TOKENS) + .build() + ) + .instructions("string") + .metadata( + Response.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .model(ChatModel.GPT_5_1) + .addOutput( + ResponseOutputMessage.builder() + .id("id") + .addContent( + ResponseOutputText.builder() + .addAnnotation( + ResponseOutputText.Annotation.FileCitation.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + ResponseOutputText.Logprob.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + ResponseOutputText.Logprob.TopLogprob + .builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .build() + ) + .build() + ) + .build() + ) + .status(ResponseOutputMessage.Status.IN_PROGRESS) + .build() + ) + .parallelToolCalls(true) + .temperature(1.0) + .toolChoice(ToolChoiceOptions.NONE) + .addTool( + FunctionTool.builder() + .name("name") + .parameters( + FunctionTool.Parameters.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .strict(true) + .description("description") + .build() + ) + .topP(1.0) + .background(true) + .completedAt(0.0) + .conversation(Response.Conversation.builder().id("id").build()) + .maxOutputTokens(0L) + .maxToolCalls(0L) + .previousResponseId("previous_response_id") + .prompt( + ResponsePrompt.builder() + .id("id") + .variables( + ResponsePrompt.Variables.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .version("version") + .build() + ) + .promptCacheKey("prompt-cache-key-1234") + .promptCacheRetention(Response.PromptCacheRetention.IN_MEMORY) + .reasoning( + Reasoning.builder() + .effort(ReasoningEffort.NONE) + .generateSummary(Reasoning.GenerateSummary.AUTO) + .summary(Reasoning.Summary.AUTO) + .build() + ) + .safetyIdentifier("safety-identifier-1234") + .serviceTier(Response.ServiceTier.AUTO) + .status(ResponseStatus.COMPLETED) + .text( + ResponseTextConfig.builder() + .format(ResponseFormatText.builder().build()) + .verbosity(ResponseTextConfig.Verbosity.LOW) + .build() + ) + .topLogprobs(0L) + .truncation(Response.Truncation.AUTO) + .usage( + ResponseUsage.builder() + .inputTokens(0L) + .inputTokensDetails( + ResponseUsage.InputTokensDetails.builder() + .cachedTokens(0L) + .build() + ) + .outputTokens(0L) + .outputTokensDetails( + ResponseUsage.OutputTokensDetails.builder() + .reasoningTokens(0L) + .build() + ) + .totalTokens(0L) + .build() + ) + .user("user-1234") + .build() + ) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseCustomToolCallInputDelta() { + val responseCustomToolCallInputDelta = + ResponseCustomToolCallInputDeltaEvent.builder() + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseCustomToolCallInputDelta( + responseCustomToolCallInputDelta + ) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()) + .contains(responseCustomToolCallInputDelta) + assertThat(responsesServerEvent.responseCustomToolCallInputDone()).isEmpty + } + + @Test + fun ofResponseCustomToolCallInputDeltaRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseCustomToolCallInputDelta( + ResponseCustomToolCallInputDeltaEvent.builder() + .delta("delta") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + @Test + fun ofResponseCustomToolCallInputDone() { + val responseCustomToolCallInputDone = + ResponseCustomToolCallInputDoneEvent.builder() + .input("input") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + + val responsesServerEvent = + ResponsesServerEvent.ofResponseCustomToolCallInputDone(responseCustomToolCallInputDone) + + assertThat(responsesServerEvent.responseAudioDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioDone()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDelta()).isEmpty + assertThat(responsesServerEvent.responseAudioTranscriptDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDelta()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCodeDone()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseCodeInterpreterCallInterpreting()).isEmpty + assertThat(responsesServerEvent.responseCompleted()).isEmpty + assertThat(responsesServerEvent.responseContentPartAdded()).isEmpty + assertThat(responsesServerEvent.responseContentPartDone()).isEmpty + assertThat(responsesServerEvent.responseCreated()).isEmpty + assertThat(responsesServerEvent.error()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseFileSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseFunctionCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseInProgress()).isEmpty + assertThat(responsesServerEvent.responseFailed()).isEmpty + assertThat(responsesServerEvent.responseIncomplete()).isEmpty + assertThat(responsesServerEvent.responseOutputItemAdded()).isEmpty + assertThat(responsesServerEvent.responseOutputItemDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartAdded()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryPartDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningSummaryTextDone()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDelta()).isEmpty + assertThat(responsesServerEvent.responseReasoningTextDone()).isEmpty + assertThat(responsesServerEvent.responseRefusalDelta()).isEmpty + assertThat(responsesServerEvent.responseRefusalDone()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDelta()).isEmpty + assertThat(responsesServerEvent.responseOutputTextDone()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseWebSearchCallSearching()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallGenerating()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseImageGenerationCallPartialImage()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDelta()).isEmpty + assertThat(responsesServerEvent.responseMcpCallArgumentsDone()).isEmpty + assertThat(responsesServerEvent.responseMcpCallCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpCallFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpCallInProgress()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsCompleted()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsFailed()).isEmpty + assertThat(responsesServerEvent.responseMcpListToolsInProgress()).isEmpty + assertThat(responsesServerEvent.responseOutputTextAnnotationAdded()).isEmpty + assertThat(responsesServerEvent.responseQueued()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDelta()).isEmpty + assertThat(responsesServerEvent.responseCustomToolCallInputDone()) + .contains(responseCustomToolCallInputDone) + } + + @Test + fun ofResponseCustomToolCallInputDoneRoundtrip() { + val jsonMapper = jsonMapper() + val responsesServerEvent = + ResponsesServerEvent.ofResponseCustomToolCallInputDone( + ResponseCustomToolCallInputDoneEvent.builder() + .input("input") + .itemId("item_id") + .outputIndex(0L) + .sequenceNumber(0L) + .build() + ) + + val roundtrippedResponsesServerEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responsesServerEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponsesServerEvent).isEqualTo(responsesServerEvent) + } + + enum class IncompatibleJsonShapeTestCase(val value: JsonValue) { + BOOLEAN(JsonValue.from(false)), + STRING(JsonValue.from("invalid")), + INTEGER(JsonValue.from(-1)), + FLOAT(JsonValue.from(3.14)), + ARRAY(JsonValue.from(listOf("invalid", "array"))), + } + + @ParameterizedTest + @EnumSource + fun incompatibleJsonShapeDeserializesToUnknown(testCase: IncompatibleJsonShapeTestCase) { + val responsesServerEvent = + jsonMapper().convertValue(testCase.value, jacksonTypeRef()) + + val e = assertThrows { responsesServerEvent.validate() } + assertThat(e).hasMessageStartingWith("Unknown ") + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/CompletionServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/CompletionServiceAsyncTest.kt index e10689427..f7abb8b4f 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/async/CompletionServiceAsyncTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/CompletionServiceAsyncTest.kt @@ -7,6 +7,7 @@ import com.openai.client.okhttp.OpenAIOkHttpClientAsync import com.openai.core.JsonValue import com.openai.models.chat.completions.ChatCompletionStreamOptions import com.openai.models.completions.CompletionCreateParams +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -58,6 +59,7 @@ internal class CompletionServiceAsyncTest { completion.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createStreaming() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/ImageServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/ImageServiceAsyncTest.kt index 0c71f5c41..9b80d4d79 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/async/ImageServiceAsyncTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/ImageServiceAsyncTest.kt @@ -8,6 +8,7 @@ import com.openai.models.images.ImageCreateVariationParams import com.openai.models.images.ImageEditParams import com.openai.models.images.ImageGenerateParams import com.openai.models.images.ImageModel +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -72,6 +73,7 @@ internal class ImageServiceAsyncTest { imagesResponse.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun editStreaming() { val client = @@ -140,6 +142,7 @@ internal class ImageServiceAsyncTest { imagesResponse.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun generateStreaming() { val client = 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 d24c9ddf4..67da7864e 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 @@ -17,6 +17,7 @@ import com.openai.models.responses.ResponsePrompt import com.openai.models.responses.ResponseRetrieveParams import com.openai.models.responses.ResponseTextConfig import com.openai.models.responses.ToolChoiceOptions +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -115,6 +116,7 @@ internal class ResponseServiceAsyncTest { response.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createStreaming() { val client = @@ -231,6 +233,7 @@ internal class ResponseServiceAsyncTest { response.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun retrieveStreaming() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncTest.kt index e67386f35..cc9a56661 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncTest.kt @@ -8,6 +8,7 @@ import com.openai.models.audio.AudioModel import com.openai.models.audio.AudioResponseFormat import com.openai.models.audio.transcriptions.TranscriptionCreateParams import com.openai.models.audio.transcriptions.TranscriptionInclude +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -44,6 +45,7 @@ internal class TranscriptionServiceAsyncTest { transcription.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createStreaming() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/beta/ThreadServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/beta/ThreadServiceAsyncTest.kt index 1f7504e2d..4cf857c6d 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/async/beta/ThreadServiceAsyncTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/beta/ThreadServiceAsyncTest.kt @@ -11,6 +11,7 @@ import com.openai.models.beta.threads.AssistantToolChoiceOption import com.openai.models.beta.threads.ThreadCreateAndRunParams import com.openai.models.beta.threads.ThreadCreateParams import com.openai.models.beta.threads.ThreadUpdateParams +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -279,6 +280,7 @@ internal class ThreadServiceAsyncTest { run.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createAndRunStreaming() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/beta/threads/RunServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/beta/threads/RunServiceAsyncTest.kt index 9cab60493..a4af25501 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/async/beta/threads/RunServiceAsyncTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/beta/threads/RunServiceAsyncTest.kt @@ -15,6 +15,7 @@ import com.openai.models.beta.threads.runs.RunRetrieveParams import com.openai.models.beta.threads.runs.RunSubmitToolOutputsParams import com.openai.models.beta.threads.runs.RunUpdateParams import com.openai.models.beta.threads.runs.steps.RunStepInclude +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -83,6 +84,7 @@ internal class RunServiceAsyncTest { run.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createStreaming() { val client = @@ -250,6 +252,7 @@ internal class RunServiceAsyncTest { run.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun submitToolOutputsStreaming() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/chat/ChatCompletionServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/chat/ChatCompletionServiceAsyncTest.kt index 509010d79..88be21c67 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/async/chat/ChatCompletionServiceAsyncTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/chat/ChatCompletionServiceAsyncTest.kt @@ -17,6 +17,7 @@ import com.openai.models.chat.completions.ChatCompletionPredictionContent import com.openai.models.chat.completions.ChatCompletionStreamOptions import com.openai.models.chat.completions.ChatCompletionToolChoiceOption import com.openai.models.chat.completions.ChatCompletionUpdateParams +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -140,6 +141,7 @@ internal class ChatCompletionServiceAsyncTest { chatCompletion.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createStreaming() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/CompletionServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/CompletionServiceTest.kt index 7d9148b27..4beabebe1 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/blocking/CompletionServiceTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/CompletionServiceTest.kt @@ -7,6 +7,7 @@ import com.openai.client.okhttp.OpenAIOkHttpClient import com.openai.core.JsonValue import com.openai.models.chat.completions.ChatCompletionStreamOptions import com.openai.models.completions.CompletionCreateParams +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -57,6 +58,7 @@ internal class CompletionServiceTest { completion.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createStreaming() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/ImageServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/ImageServiceTest.kt index 0c6b44d31..3bbcd3a11 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/blocking/ImageServiceTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/ImageServiceTest.kt @@ -8,6 +8,7 @@ import com.openai.models.images.ImageCreateVariationParams import com.openai.models.images.ImageEditParams import com.openai.models.images.ImageGenerateParams import com.openai.models.images.ImageModel +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -70,6 +71,7 @@ internal class ImageServiceTest { imagesResponse.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun editStreaming() { val client = @@ -137,6 +139,7 @@ internal class ImageServiceTest { imagesResponse.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun generateStreaming() { val client = 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 e6adc4273..ed4bda8e6 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 @@ -17,6 +17,7 @@ import com.openai.models.responses.ResponsePrompt import com.openai.models.responses.ResponseRetrieveParams import com.openai.models.responses.ResponseTextConfig import com.openai.models.responses.ToolChoiceOptions +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -114,6 +115,7 @@ internal class ResponseServiceTest { response.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createStreaming() { val client = @@ -229,6 +231,7 @@ internal class ResponseServiceTest { response.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun retrieveStreaming() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/audio/TranscriptionServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/audio/TranscriptionServiceTest.kt index 3aa73eb10..8c84d5f9c 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/blocking/audio/TranscriptionServiceTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/audio/TranscriptionServiceTest.kt @@ -8,6 +8,7 @@ import com.openai.models.audio.AudioModel import com.openai.models.audio.AudioResponseFormat import com.openai.models.audio.transcriptions.TranscriptionCreateParams import com.openai.models.audio.transcriptions.TranscriptionInclude +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -43,6 +44,7 @@ internal class TranscriptionServiceTest { transcription.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createStreaming() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/beta/ThreadServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/beta/ThreadServiceTest.kt index 1b3013148..6c13c4233 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/blocking/beta/ThreadServiceTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/beta/ThreadServiceTest.kt @@ -11,6 +11,7 @@ import com.openai.models.beta.threads.AssistantToolChoiceOption import com.openai.models.beta.threads.ThreadCreateAndRunParams import com.openai.models.beta.threads.ThreadCreateParams import com.openai.models.beta.threads.ThreadUpdateParams +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -274,6 +275,7 @@ internal class ThreadServiceTest { run.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createAndRunStreaming() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/beta/threads/RunServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/beta/threads/RunServiceTest.kt index 38735ff28..64227e1d0 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/blocking/beta/threads/RunServiceTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/beta/threads/RunServiceTest.kt @@ -15,6 +15,7 @@ import com.openai.models.beta.threads.runs.RunRetrieveParams import com.openai.models.beta.threads.runs.RunSubmitToolOutputsParams import com.openai.models.beta.threads.runs.RunUpdateParams import com.openai.models.beta.threads.runs.steps.RunStepInclude +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -82,6 +83,7 @@ internal class RunServiceTest { run.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createStreaming() { val client = @@ -242,6 +244,7 @@ internal class RunServiceTest { run.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun submitToolOutputsStreaming() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/chat/ChatCompletionServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/chat/ChatCompletionServiceTest.kt index a5bb516af..eff150078 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/blocking/chat/ChatCompletionServiceTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/chat/ChatCompletionServiceTest.kt @@ -17,6 +17,7 @@ import com.openai.models.chat.completions.ChatCompletionPredictionContent import com.openai.models.chat.completions.ChatCompletionStreamOptions import com.openai.models.chat.completions.ChatCompletionToolChoiceOption import com.openai.models.chat.completions.ChatCompletionUpdateParams +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -139,6 +140,7 @@ internal class ChatCompletionServiceTest { chatCompletion.validate() } + @Disabled("Prism does not support SSE streaming mock responses") @Test fun createStreaming() { val client =