diff --git a/.github/workflows/create-releases.yml b/.github/workflows/create-releases.yml index f7b805807..6f33bfbfd 100644 --- a/.github/workflows/create-releases.yml +++ b/.github/workflows/create-releases.yml @@ -73,7 +73,7 @@ jobs: export -- GPG_SIGNING_KEY_ID printenv -- GPG_SIGNING_KEY | gpg --batch --passphrase-fd 3 --import 3<<< "$GPG_SIGNING_PASSWORD" GPG_SIGNING_KEY_ID="$(gpg --with-colons --list-keys | awk -F : -- '/^pub:/ { getline; print "0x" substr($10, length($10) - 7) }')" - ./gradlew publishAndReleaseToMavenCentral -Dorg.gradle.jvmargs="-Xmx8g" --stacktrace -PmavenCentralUsername="$SONATYPE_USERNAME" -PmavenCentralPassword="$SONATYPE_PASSWORD" --no-configuration-cache + ./gradlew publishAndReleaseToMavenCentral --stacktrace -PmavenCentralUsername="$SONATYPE_USERNAME" -PmavenCentralPassword="$SONATYPE_PASSWORD" --no-configuration-cache env: SONATYPE_USERNAME: ${{ secrets.OPENAI_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }} SONATYPE_PASSWORD: ${{ secrets.OPENAI_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }} diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml index 55c74a194..74d7139c6 100644 --- a/.github/workflows/publish-sonatype.yml +++ b/.github/workflows/publish-sonatype.yml @@ -60,7 +60,7 @@ jobs: export -- GPG_SIGNING_KEY_ID printenv -- GPG_SIGNING_KEY | gpg --batch --passphrase-fd 3 --import 3<<< "$GPG_SIGNING_PASSWORD" GPG_SIGNING_KEY_ID="$(gpg --with-colons --list-keys | awk -F : -- '/^pub:/ { getline; print "0x" substr($10, length($10) - 7) }')" - ./gradlew publishAndReleaseToMavenCentral -Dorg.gradle.jvmargs="-Xmx8g" --stacktrace -PmavenCentralUsername="$SONATYPE_USERNAME" -PmavenCentralPassword="$SONATYPE_PASSWORD" --no-configuration-cache + ./gradlew publishAndReleaseToMavenCentral --stacktrace -PmavenCentralUsername="$SONATYPE_USERNAME" -PmavenCentralPassword="$SONATYPE_PASSWORD" --no-configuration-cache env: SONATYPE_USERNAME: ${{ secrets.OPENAI_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }} SONATYPE_PASSWORD: ${{ secrets.OPENAI_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 9d7db69f9..1f73031b8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.1.2" + ".": "3.2.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index d4994342f..f2d5304a5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 111 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-7ef7a457c3bf05364e66e48c9ca34f31bfef1f6c9b7c15b1812346105e0abb16.yml -openapi_spec_hash: a2b1f5d8fbb62175c93b0ebea9f10063 -config_hash: 4870312b04f48fd717ea4151053e7fb9 +configured_endpoints: 119 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-ddbdf9343316047e8a773c54fb24e4a8d225955e202a1888fde6f9c8898ebf98.yml +openapi_spec_hash: 9802f6dd381558466c897f6e387e06ca +config_hash: fe0ea26680ac2075a6cd66416aefe7db diff --git a/CHANGELOG.md b/CHANGELOG.md index fd6798f1a..14b1a7abe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## 3.2.0 (2025-08-22) + +Full Changelog: [v3.1.2...v3.2.0](https://github.com/openai/openai-java/compare/v3.1.2...v3.2.0) + +### Features + +* **api:** Add connectors support for MCP tool ([ee175a9](https://github.com/openai/openai-java/commit/ee175a98a1ed4f1e939c301dd5bf62f10e367c6c)) +* **api:** adding support for /v1/conversations to the API ([9d088c5](https://github.com/openai/openai-java/commit/9d088c5d77c450a2e1371a8293e9c05ebf102937)) + + +### Chores + +* add missing delegate methods ([557e9ee](https://github.com/openai/openai-java/commit/557e9ee897e11c95788300922e8094383eb1dd97)) +* **ci:** reduce log noise ([9e91952](https://github.com/openai/openai-java/commit/9e9195269a225cdbaba81e2dd6ee26caba407d00)) +* **client:** refactor closing / shutdown ([94cdfcd](https://github.com/openai/openai-java/commit/94cdfcdf57225ee606acf51ffe3e0b6a4321f7e6)) +* **internal:** support running formatters directly ([6242da5](https://github.com/openai/openai-java/commit/6242da594134e736470c006bc1af6b38ce757705)) +* remove memory upper bound from publishing step ([fdc5fdd](https://github.com/openai/openai-java/commit/fdc5fdd3969d2ecc3d6df1546b34167b63074991)) + ## 3.1.2 (2025-08-20) Full Changelog: [v3.1.1...v3.1.2](https://github.com/openai/openai-java/compare/v3.1.1...v3.1.2) diff --git a/README.md b/README.md index 4b10773ef..3c2ea9a32 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/3.1.2) -[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/3.1.2/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/3.1.2) +[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/3.2.0) +[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/3.2.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/3.2.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/3.1.2). +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/3.2.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:3.1.2") +implementation("com.openai:openai-java:3.2.0") ``` ### Maven @@ -33,7 +33,7 @@ implementation("com.openai:openai-java:3.1.2") com.openai openai-java - 3.1.2 + 3.2.0 ``` @@ -1330,7 +1330,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:3.1.2") +implementation("com.openai:openai-java-spring-boot-starter:3.2.0") ``` #### Maven @@ -1339,7 +1339,7 @@ implementation("com.openai:openai-java-spring-boot-starter:3.1.2") com.openai openai-java-spring-boot-starter - 3.1.2 + 3.2.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index 7108208f7..435360279 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.openai" - version = "3.1.2" // x-release-please-version + version = "3.2.0" // x-release-please-version } subprojects { diff --git a/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt b/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt index 61e6fcd13..353f94f1c 100644 --- a/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt +++ b/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt @@ -128,6 +128,8 @@ class OpenAIOkHttpClient private constructor() { * The executor to use for running [AsyncStreamResponse.Handler] callbacks. * * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. */ fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { clientOptions.streamHandlerExecutor(streamHandlerExecutor) diff --git a/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt b/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt index c840742ec..9707fffb3 100644 --- a/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt +++ b/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt @@ -128,6 +128,8 @@ class OpenAIOkHttpClientAsync private constructor() { * The executor to use for running [AsyncStreamResponse.Handler] callbacks. * * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. */ fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { clientOptions.streamHandlerExecutor(streamHandlerExecutor) diff --git a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClient.kt b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClient.kt index 692262752..5b6e67724 100644 --- a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClient.kt +++ b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClient.kt @@ -9,6 +9,7 @@ import com.openai.services.blocking.BetaService import com.openai.services.blocking.ChatService import com.openai.services.blocking.CompletionService import com.openai.services.blocking.ContainerService +import com.openai.services.blocking.ConversationService import com.openai.services.blocking.EmbeddingService import com.openai.services.blocking.EvalService import com.openai.services.blocking.FileService @@ -91,6 +92,8 @@ interface OpenAIClient { fun responses(): ResponseService + fun conversations(): ConversationService + fun evals(): EvalService fun containers(): ContainerService @@ -150,6 +153,8 @@ interface OpenAIClient { fun responses(): ResponseService.WithRawResponse + fun conversations(): ConversationService.WithRawResponse + fun evals(): EvalService.WithRawResponse fun containers(): ContainerService.WithRawResponse diff --git a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsync.kt b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsync.kt index a0369ca4a..00c1d5d59 100644 --- a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsync.kt +++ b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsync.kt @@ -9,6 +9,7 @@ import com.openai.services.async.BetaServiceAsync import com.openai.services.async.ChatServiceAsync import com.openai.services.async.CompletionServiceAsync import com.openai.services.async.ContainerServiceAsync +import com.openai.services.async.ConversationServiceAsync import com.openai.services.async.EmbeddingServiceAsync import com.openai.services.async.EvalServiceAsync import com.openai.services.async.FileServiceAsync @@ -91,6 +92,8 @@ interface OpenAIClientAsync { fun responses(): ResponseServiceAsync + fun conversations(): ConversationServiceAsync + fun evals(): EvalServiceAsync fun containers(): ContainerServiceAsync @@ -152,6 +155,8 @@ interface OpenAIClientAsync { fun responses(): ResponseServiceAsync.WithRawResponse + fun conversations(): ConversationServiceAsync.WithRawResponse + fun evals(): EvalServiceAsync.WithRawResponse fun containers(): ContainerServiceAsync.WithRawResponse diff --git a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt index 73edf7d11..8dca941d0 100644 --- a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt @@ -16,6 +16,8 @@ import com.openai.services.async.CompletionServiceAsync import com.openai.services.async.CompletionServiceAsyncImpl import com.openai.services.async.ContainerServiceAsync import com.openai.services.async.ContainerServiceAsyncImpl +import com.openai.services.async.ConversationServiceAsync +import com.openai.services.async.ConversationServiceAsyncImpl import com.openai.services.async.EmbeddingServiceAsync import com.openai.services.async.EmbeddingServiceAsyncImpl import com.openai.services.async.EvalServiceAsync @@ -117,6 +119,10 @@ class OpenAIClientAsyncImpl(private val clientOptions: ClientOptions) : OpenAICl ResponseServiceAsyncImpl(clientOptionsWithUserAgent) } + private val conversations: ConversationServiceAsync by lazy { + ConversationServiceAsyncImpl(clientOptionsWithUserAgent) + } + private val evals: EvalServiceAsync by lazy { EvalServiceAsyncImpl(clientOptionsWithUserAgent) } private val containers: ContainerServiceAsync by lazy { @@ -162,11 +168,13 @@ class OpenAIClientAsyncImpl(private val clientOptions: ClientOptions) : OpenAICl override fun responses(): ResponseServiceAsync = responses + override fun conversations(): ConversationServiceAsync = conversations + override fun evals(): EvalServiceAsync = evals override fun containers(): ContainerServiceAsync = containers - override fun close() = clientOptions.httpClient.close() + override fun close() = clientOptions.close() class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : OpenAIClientAsync.WithRawResponse { @@ -235,6 +243,10 @@ class OpenAIClientAsyncImpl(private val clientOptions: ClientOptions) : OpenAICl ResponseServiceAsyncImpl.WithRawResponseImpl(clientOptions) } + private val conversations: ConversationServiceAsync.WithRawResponse by lazy { + ConversationServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + private val evals: EvalServiceAsync.WithRawResponse by lazy { EvalServiceAsyncImpl.WithRawResponseImpl(clientOptions) } @@ -282,6 +294,8 @@ class OpenAIClientAsyncImpl(private val clientOptions: ClientOptions) : OpenAICl override fun responses(): ResponseServiceAsync.WithRawResponse = responses + override fun conversations(): ConversationServiceAsync.WithRawResponse = conversations + override fun evals(): EvalServiceAsync.WithRawResponse = evals override fun containers(): ContainerServiceAsync.WithRawResponse = containers diff --git a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt index c54e85de5..c7d4d9420 100644 --- a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt @@ -16,6 +16,8 @@ import com.openai.services.blocking.CompletionService import com.openai.services.blocking.CompletionServiceImpl import com.openai.services.blocking.ContainerService import com.openai.services.blocking.ContainerServiceImpl +import com.openai.services.blocking.ConversationService +import com.openai.services.blocking.ConversationServiceImpl import com.openai.services.blocking.EmbeddingService import com.openai.services.blocking.EmbeddingServiceImpl import com.openai.services.blocking.EvalService @@ -103,6 +105,10 @@ class OpenAIClientImpl(private val clientOptions: ClientOptions) : OpenAIClient ResponseServiceImpl(clientOptionsWithUserAgent) } + private val conversations: ConversationService by lazy { + ConversationServiceImpl(clientOptionsWithUserAgent) + } + private val evals: EvalService by lazy { EvalServiceImpl(clientOptionsWithUserAgent) } private val containers: ContainerService by lazy { @@ -148,11 +154,13 @@ class OpenAIClientImpl(private val clientOptions: ClientOptions) : OpenAIClient override fun responses(): ResponseService = responses + override fun conversations(): ConversationService = conversations + override fun evals(): EvalService = evals override fun containers(): ContainerService = containers - override fun close() = clientOptions.httpClient.close() + override fun close() = clientOptions.close() class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : OpenAIClient.WithRawResponse { @@ -221,6 +229,10 @@ class OpenAIClientImpl(private val clientOptions: ClientOptions) : OpenAIClient ResponseServiceImpl.WithRawResponseImpl(clientOptions) } + private val conversations: ConversationService.WithRawResponse by lazy { + ConversationServiceImpl.WithRawResponseImpl(clientOptions) + } + private val evals: EvalService.WithRawResponse by lazy { EvalServiceImpl.WithRawResponseImpl(clientOptions) } @@ -268,6 +280,8 @@ class OpenAIClientImpl(private val clientOptions: ClientOptions) : OpenAIClient override fun responses(): ResponseService.WithRawResponse = responses + override fun conversations(): ConversationService.WithRawResponse = conversations + override fun evals(): EvalService.WithRawResponse = evals override fun containers(): ContainerService.WithRawResponse = containers diff --git a/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt b/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt index e7e4f4221..515eb4f49 100644 --- a/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt +++ b/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt @@ -19,6 +19,7 @@ import java.time.Clock import java.time.Duration import java.util.Optional import java.util.concurrent.Executor +import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.ThreadFactory import java.util.concurrent.atomic.AtomicLong @@ -32,6 +33,8 @@ private constructor( * The HTTP client to use in the SDK. * * Use the one published in `openai-java-client-okhttp` or implement your own. + * + * This class takes ownership of the client and closes it when closed. */ @get:JvmName("httpClient") val httpClient: HttpClient, /** @@ -53,6 +56,8 @@ private constructor( * The executor to use for running [AsyncStreamResponse.Handler] callbacks. * * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. */ @get:JvmName("streamHandlerExecutor") val streamHandlerExecutor: Executor, /** @@ -196,6 +201,8 @@ private constructor( * The HTTP client to use in the SDK. * * Use the one published in `openai-java-client-okhttp` or implement your own. + * + * This class takes ownership of the client and closes it when closed. */ fun httpClient(httpClient: HttpClient) = apply { this.httpClient = PhantomReachableClosingHttpClient(httpClient) @@ -224,9 +231,14 @@ private constructor( * The executor to use for running [AsyncStreamResponse.Handler] callbacks. * * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. */ fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { - this.streamHandlerExecutor = streamHandlerExecutor + this.streamHandlerExecutor = + if (streamHandlerExecutor is ExecutorService) + PhantomReachableExecutorService(streamHandlerExecutor) + else streamHandlerExecutor } /** @@ -554,4 +566,19 @@ private constructor( ) } } + + /** + * Closes these client options, relinquishing any underlying resources. + * + * This is purposefully not inherited from [AutoCloseable] because the client options are + * long-lived and usually should not be synchronously closed via try-with-resources. + * + * It's also usually not necessary to call this method at all. the default client automatically + * releases threads and connections if they remain idle, but if you are writing an application + * that needs to aggressively release unused resources, then you may call this method. + */ + fun close() { + httpClient.close() + (streamHandlerExecutor as? ExecutorService)?.shutdown() + } } diff --git a/openai-java-core/src/main/kotlin/com/openai/core/PhantomReachableExecutorService.kt b/openai-java-core/src/main/kotlin/com/openai/core/PhantomReachableExecutorService.kt new file mode 100644 index 000000000..250071c78 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/core/PhantomReachableExecutorService.kt @@ -0,0 +1,58 @@ +package com.openai.core + +import java.util.concurrent.Callable +import java.util.concurrent.ExecutorService +import java.util.concurrent.Future +import java.util.concurrent.TimeUnit + +/** + * A delegating wrapper around an [ExecutorService] that shuts it down once it's only phantom + * reachable. + * + * This class ensures the [ExecutorService] is shut down even if the user forgets to do it. + */ +internal class PhantomReachableExecutorService(private val executorService: ExecutorService) : + ExecutorService { + init { + closeWhenPhantomReachable(this) { executorService.shutdown() } + } + + override fun execute(command: Runnable) = executorService.execute(command) + + override fun shutdown() = executorService.shutdown() + + override fun shutdownNow(): MutableList = executorService.shutdownNow() + + override fun isShutdown(): Boolean = executorService.isShutdown + + override fun isTerminated(): Boolean = executorService.isTerminated + + override fun awaitTermination(timeout: Long, unit: TimeUnit): Boolean = + executorService.awaitTermination(timeout, unit) + + override fun submit(task: Callable): Future = executorService.submit(task) + + override fun submit(task: Runnable, result: T): Future = + executorService.submit(task, result) + + override fun submit(task: Runnable): Future<*> = executorService.submit(task) + + override fun invokeAll( + tasks: MutableCollection> + ): MutableList> = executorService.invokeAll(tasks) + + override fun invokeAll( + tasks: MutableCollection>, + timeout: Long, + unit: TimeUnit, + ): MutableList> = executorService.invokeAll(tasks, timeout, unit) + + override fun invokeAny(tasks: MutableCollection>): T = + executorService.invokeAny(tasks) + + override fun invokeAny( + tasks: MutableCollection>, + timeout: Long, + unit: TimeUnit, + ): T = executorService.invokeAny(tasks, timeout, unit) +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ComputerScreenshotContent.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ComputerScreenshotContent.kt new file mode 100644 index 000000000..39efe0bb0 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ComputerScreenshotContent.kt @@ -0,0 +1,258 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class ComputerScreenshotContent +private constructor( + private val fileId: JsonField, + private val imageUrl: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("file_id") @ExcludeMissing fileId: JsonField = JsonMissing.of(), + @JsonProperty("image_url") @ExcludeMissing imageUrl: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(fileId, imageUrl, type, mutableMapOf()) + + /** + * The identifier of an uploaded file that contains the screenshot. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun fileId(): Optional = fileId.getOptional("file_id") + + /** + * The URL of the screenshot image. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun imageUrl(): Optional = imageUrl.getOptional("image_url") + + /** + * Specifies the event type. For a computer screenshot, this property is always set to + * `computer_screenshot`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("computer_screenshot") + * ``` + * + * 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 + + /** + * Returns the raw JSON value of [fileId]. + * + * Unlike [fileId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId + + /** + * Returns the raw JSON value of [imageUrl]. + * + * Unlike [imageUrl], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("image_url") @ExcludeMissing fun _imageUrl(): JsonField = imageUrl + + @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 [ComputerScreenshotContent]. + * + * The following fields are required: + * ```java + * .fileId() + * .imageUrl() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ComputerScreenshotContent]. */ + class Builder internal constructor() { + + private var fileId: JsonField? = null + private var imageUrl: JsonField? = null + private var type: JsonValue = JsonValue.from("computer_screenshot") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(computerScreenshotContent: ComputerScreenshotContent) = apply { + fileId = computerScreenshotContent.fileId + imageUrl = computerScreenshotContent.imageUrl + type = computerScreenshotContent.type + additionalProperties = computerScreenshotContent.additionalProperties.toMutableMap() + } + + /** The identifier of an uploaded file that contains the screenshot. */ + fun fileId(fileId: String?) = fileId(JsonField.ofNullable(fileId)) + + /** Alias for calling [Builder.fileId] with `fileId.orElse(null)`. */ + fun fileId(fileId: Optional) = fileId(fileId.getOrNull()) + + /** + * Sets [Builder.fileId] to an arbitrary JSON value. + * + * You should usually call [Builder.fileId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } + + /** The URL of the screenshot image. */ + fun imageUrl(imageUrl: String?) = imageUrl(JsonField.ofNullable(imageUrl)) + + /** Alias for calling [Builder.imageUrl] with `imageUrl.orElse(null)`. */ + fun imageUrl(imageUrl: Optional) = imageUrl(imageUrl.getOrNull()) + + /** + * Sets [Builder.imageUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.imageUrl] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun imageUrl(imageUrl: JsonField) = apply { this.imageUrl = imageUrl } + + /** + * 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("computer_screenshot") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [ComputerScreenshotContent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .fileId() + * .imageUrl() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ComputerScreenshotContent = + ComputerScreenshotContent( + checkRequired("fileId", fileId), + checkRequired("imageUrl", imageUrl), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ComputerScreenshotContent = apply { + if (validated) { + return@apply + } + + fileId() + imageUrl() + _type().let { + if (it != JsonValue.from("computer_screenshot")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 (fileId.asKnown().isPresent) 1 else 0) + + (if (imageUrl.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("computer_screenshot")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ComputerScreenshotContent && + fileId == other.fileId && + imageUrl == other.imageUrl && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(fileId, imageUrl, type, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ComputerScreenshotContent{fileId=$fileId, imageUrl=$imageUrl, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ContainerFileCitationBody.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ContainerFileCitationBody.kt new file mode 100644 index 000000000..67c0ff2d5 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ContainerFileCitationBody.kt @@ -0,0 +1,372 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +class ContainerFileCitationBody +private constructor( + private val containerId: JsonField, + private val endIndex: JsonField, + private val fileId: JsonField, + private val filename: JsonField, + private val startIndex: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("container_id") + @ExcludeMissing + containerId: JsonField = JsonMissing.of(), + @JsonProperty("end_index") @ExcludeMissing endIndex: JsonField = JsonMissing.of(), + @JsonProperty("file_id") @ExcludeMissing fileId: JsonField = JsonMissing.of(), + @JsonProperty("filename") @ExcludeMissing filename: JsonField = JsonMissing.of(), + @JsonProperty("start_index") @ExcludeMissing startIndex: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(containerId, endIndex, fileId, filename, startIndex, type, mutableMapOf()) + + /** + * The ID of the container file. + * + * @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 containerId(): String = containerId.getRequired("container_id") + + /** + * The index of the last character of the container file citation in the message. + * + * @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 endIndex(): Long = endIndex.getRequired("end_index") + + /** + * The ID of the file. + * + * @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 fileId(): String = fileId.getRequired("file_id") + + /** + * The filename of the container file cited. + * + * @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 filename(): String = filename.getRequired("filename") + + /** + * The index of the first character of the container file citation in the message. + * + * @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 startIndex(): Long = startIndex.getRequired("start_index") + + /** + * The type of the container file citation. Always `container_file_citation`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("container_file_citation") + * ``` + * + * 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 + + /** + * Returns the raw JSON value of [containerId]. + * + * Unlike [containerId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("container_id") + @ExcludeMissing + fun _containerId(): JsonField = containerId + + /** + * Returns the raw JSON value of [endIndex]. + * + * Unlike [endIndex], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("end_index") @ExcludeMissing fun _endIndex(): JsonField = endIndex + + /** + * Returns the raw JSON value of [fileId]. + * + * Unlike [fileId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId + + /** + * Returns the raw JSON value of [filename]. + * + * Unlike [filename], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("filename") @ExcludeMissing fun _filename(): JsonField = filename + + /** + * Returns the raw JSON value of [startIndex]. + * + * Unlike [startIndex], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("start_index") @ExcludeMissing fun _startIndex(): JsonField = startIndex + + @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 [ContainerFileCitationBody]. + * + * The following fields are required: + * ```java + * .containerId() + * .endIndex() + * .fileId() + * .filename() + * .startIndex() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ContainerFileCitationBody]. */ + class Builder internal constructor() { + + private var containerId: JsonField? = null + private var endIndex: JsonField? = null + private var fileId: JsonField? = null + private var filename: JsonField? = null + private var startIndex: JsonField? = null + private var type: JsonValue = JsonValue.from("container_file_citation") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(containerFileCitationBody: ContainerFileCitationBody) = apply { + containerId = containerFileCitationBody.containerId + endIndex = containerFileCitationBody.endIndex + fileId = containerFileCitationBody.fileId + filename = containerFileCitationBody.filename + startIndex = containerFileCitationBody.startIndex + type = containerFileCitationBody.type + additionalProperties = containerFileCitationBody.additionalProperties.toMutableMap() + } + + /** The ID of the container file. */ + fun containerId(containerId: String) = containerId(JsonField.of(containerId)) + + /** + * Sets [Builder.containerId] to an arbitrary JSON value. + * + * You should usually call [Builder.containerId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun containerId(containerId: JsonField) = apply { this.containerId = containerId } + + /** The index of the last character of the container file citation in the message. */ + fun endIndex(endIndex: Long) = endIndex(JsonField.of(endIndex)) + + /** + * Sets [Builder.endIndex] to an arbitrary JSON value. + * + * You should usually call [Builder.endIndex] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun endIndex(endIndex: JsonField) = apply { this.endIndex = endIndex } + + /** The ID of the file. */ + fun fileId(fileId: String) = fileId(JsonField.of(fileId)) + + /** + * Sets [Builder.fileId] to an arbitrary JSON value. + * + * You should usually call [Builder.fileId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } + + /** The filename of the container file cited. */ + fun filename(filename: String) = filename(JsonField.of(filename)) + + /** + * Sets [Builder.filename] to an arbitrary JSON value. + * + * You should usually call [Builder.filename] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun filename(filename: JsonField) = apply { this.filename = filename } + + /** The index of the first character of the container file citation in the message. */ + fun startIndex(startIndex: Long) = startIndex(JsonField.of(startIndex)) + + /** + * Sets [Builder.startIndex] to an arbitrary JSON value. + * + * You should usually call [Builder.startIndex] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun startIndex(startIndex: JsonField) = apply { this.startIndex = startIndex } + + /** + * 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("container_file_citation") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [ContainerFileCitationBody]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .containerId() + * .endIndex() + * .fileId() + * .filename() + * .startIndex() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ContainerFileCitationBody = + ContainerFileCitationBody( + checkRequired("containerId", containerId), + checkRequired("endIndex", endIndex), + checkRequired("fileId", fileId), + checkRequired("filename", filename), + checkRequired("startIndex", startIndex), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ContainerFileCitationBody = apply { + if (validated) { + return@apply + } + + containerId() + endIndex() + fileId() + filename() + startIndex() + _type().let { + if (it != JsonValue.from("container_file_citation")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 (containerId.asKnown().isPresent) 1 else 0) + + (if (endIndex.asKnown().isPresent) 1 else 0) + + (if (fileId.asKnown().isPresent) 1 else 0) + + (if (filename.asKnown().isPresent) 1 else 0) + + (if (startIndex.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("container_file_citation")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ContainerFileCitationBody && + containerId == other.containerId && + endIndex == other.endIndex && + fileId == other.fileId && + filename == other.filename && + startIndex == other.startIndex && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + containerId, + endIndex, + fileId, + filename, + startIndex, + type, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ContainerFileCitationBody{containerId=$containerId, endIndex=$endIndex, fileId=$fileId, filename=$filename, startIndex=$startIndex, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/Conversation.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/Conversation.kt new file mode 100644 index 000000000..56a086785 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/Conversation.kt @@ -0,0 +1,277 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +class Conversation +private constructor( + private val id: JsonField, + private val createdAt: JsonField, + private val metadata: JsonValue, + private val object_: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("created_at") @ExcludeMissing createdAt: JsonField = JsonMissing.of(), + @JsonProperty("metadata") @ExcludeMissing metadata: JsonValue = JsonMissing.of(), + @JsonProperty("object") @ExcludeMissing object_: JsonValue = JsonMissing.of(), + ) : this(id, createdAt, metadata, object_, mutableMapOf()) + + /** + * The unique ID of the conversation. + * + * @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 id(): String = id.getRequired("id") + + /** + * The time at which the conversation was created, measured in seconds since the Unix epoch. + * + * @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 createdAt(): Long = createdAt.getRequired("created_at") + + /** + * 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. + */ + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** + * The object type, which is always `conversation`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("conversation") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). + */ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonValue = object_ + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [createdAt]. + * + * Unlike [createdAt], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("created_at") @ExcludeMissing fun _createdAt(): JsonField = createdAt + + @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 [Conversation]. + * + * The following fields are required: + * ```java + * .id() + * .createdAt() + * .metadata() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Conversation]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var createdAt: JsonField? = null + private var metadata: JsonValue? = null + private var object_: JsonValue = JsonValue.from("conversation") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(conversation: Conversation) = apply { + id = conversation.id + createdAt = conversation.createdAt + metadata = conversation.metadata + object_ = conversation.object_ + additionalProperties = conversation.additionalProperties.toMutableMap() + } + + /** The unique ID of the conversation. */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** + * The time at which the conversation was created, measured in seconds since the Unix epoch. + */ + fun createdAt(createdAt: Long) = createdAt(JsonField.of(createdAt)) + + /** + * Sets [Builder.createdAt] to an arbitrary JSON value. + * + * You should usually call [Builder.createdAt] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun createdAt(createdAt: JsonField) = apply { this.createdAt = createdAt } + + /** + * 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: JsonValue) = apply { this.metadata = metadata } + + /** + * 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("conversation") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun object_(object_: JsonValue) = apply { this.object_ = object_ } + + 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 [Conversation]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .createdAt() + * .metadata() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Conversation = + Conversation( + checkRequired("id", id), + checkRequired("createdAt", createdAt), + checkRequired("metadata", metadata), + object_, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Conversation = apply { + if (validated) { + return@apply + } + + id() + createdAt() + _object_().let { + if (it != JsonValue.from("conversation")) { + throw OpenAIInvalidDataException("'object_' is invalid, received $it") + } + } + 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 (id.asKnown().isPresent) 1 else 0) + + (if (createdAt.asKnown().isPresent) 1 else 0) + + object_.let { if (it == JsonValue.from("conversation")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Conversation && + id == other.id && + createdAt == other.createdAt && + metadata == other.metadata && + object_ == other.object_ && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(id, createdAt, metadata, object_, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Conversation{id=$id, createdAt=$createdAt, metadata=$metadata, object_=$object_, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationCreateParams.kt new file mode 100644 index 000000000..bb85e5860 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationCreateParams.kt @@ -0,0 +1,921 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.Params +import com.openai.core.checkKnown +import com.openai.core.http.Headers +import com.openai.core.http.QueryParams +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import com.openai.models.responses.EasyInputMessage +import com.openai.models.responses.ResponseCodeInterpreterToolCall +import com.openai.models.responses.ResponseComputerToolCall +import com.openai.models.responses.ResponseCustomToolCall +import com.openai.models.responses.ResponseCustomToolCallOutput +import com.openai.models.responses.ResponseFileSearchToolCall +import com.openai.models.responses.ResponseFunctionToolCall +import com.openai.models.responses.ResponseFunctionWebSearch +import com.openai.models.responses.ResponseInputItem +import com.openai.models.responses.ResponseOutputMessage +import com.openai.models.responses.ResponseReasoningItem +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Create a conversation with the given ID. */ +class ConversationCreateParams +private constructor( + private val body: Body, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** + * Initial items to include in the conversation context. You may add up to 20 items at a time. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun items(): Optional> = body.items() + + /** + * Set of 16 key-value pairs that can be attached to an object. Useful for storing additional + * information about the object in a structured format. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun metadata(): Optional = body.metadata() + + /** + * Returns the raw JSON value of [items]. + * + * Unlike [items], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _items(): JsonField> = body._items() + + /** + * Returns the raw JSON value of [metadata]. + * + * Unlike [metadata], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _metadata(): JsonField = body._metadata() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): ConversationCreateParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [ConversationCreateParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConversationCreateParams]. */ + class Builder internal constructor() { + + private var body: Body.Builder = Body.builder() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(conversationCreateParams: ConversationCreateParams) = apply { + body = conversationCreateParams.body.toBuilder() + additionalHeaders = conversationCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = conversationCreateParams.additionalQueryParams.toBuilder() + } + + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [items] + * - [metadata] + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + /** + * Initial items to include in the conversation context. You may add up to 20 items at a + * time. + */ + fun items(items: List?) = apply { body.items(items) } + + /** Alias for calling [Builder.items] with `items.orElse(null)`. */ + fun items(items: Optional>) = items(items.getOrNull()) + + /** + * Sets [Builder.items] to an arbitrary JSON value. + * + * You should usually call [Builder.items] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun items(items: JsonField>) = apply { body.items(items) } + + /** + * Adds a single [ResponseInputItem] to [items]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addItem(item: ResponseInputItem) = apply { body.addItem(item) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofEasyInputMessage(easyInputMessage)`. + */ + fun addItem(easyInputMessage: EasyInputMessage) = apply { body.addItem(easyInputMessage) } + + /** Alias for calling [addItem] with `ResponseInputItem.ofMessage(message)`. */ + fun addItem(message: ResponseInputItem.Message) = apply { body.addItem(message) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofResponseOutputMessage(responseOutputMessage)`. + */ + fun addItem(responseOutputMessage: ResponseOutputMessage) = apply { + body.addItem(responseOutputMessage) + } + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofFileSearchCall(fileSearchCall)`. + */ + fun addItem(fileSearchCall: ResponseFileSearchToolCall) = apply { + body.addItem(fileSearchCall) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofComputerCall(computerCall)`. */ + fun addItem(computerCall: ResponseComputerToolCall) = apply { body.addItem(computerCall) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofComputerCallOutput(computerCallOutput)`. + */ + fun addItem(computerCallOutput: ResponseInputItem.ComputerCallOutput) = apply { + body.addItem(computerCallOutput) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofWebSearchCall(webSearchCall)`. */ + fun addItem(webSearchCall: ResponseFunctionWebSearch) = apply { + body.addItem(webSearchCall) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofFunctionCall(functionCall)`. */ + fun addItem(functionCall: ResponseFunctionToolCall) = apply { body.addItem(functionCall) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofFunctionCallOutput(functionCallOutput)`. + */ + fun addItem(functionCallOutput: ResponseInputItem.FunctionCallOutput) = apply { + body.addItem(functionCallOutput) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofReasoning(reasoning)`. */ + fun addItem(reasoning: ResponseReasoningItem) = apply { body.addItem(reasoning) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofImageGenerationCall(imageGenerationCall)`. + */ + fun addItem(imageGenerationCall: ResponseInputItem.ImageGenerationCall) = apply { + body.addItem(imageGenerationCall) + } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofCodeInterpreterCall(codeInterpreterCall)`. + */ + fun addItem(codeInterpreterCall: ResponseCodeInterpreterToolCall) = apply { + body.addItem(codeInterpreterCall) + } + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofLocalShellCall(localShellCall)`. + */ + fun addItem(localShellCall: ResponseInputItem.LocalShellCall) = apply { + body.addItem(localShellCall) + } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofLocalShellCallOutput(localShellCallOutput)`. + */ + fun addItem(localShellCallOutput: ResponseInputItem.LocalShellCallOutput) = apply { + body.addItem(localShellCallOutput) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofMcpListTools(mcpListTools)`. */ + fun addItem(mcpListTools: ResponseInputItem.McpListTools) = apply { + body.addItem(mcpListTools) + } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofMcpApprovalRequest(mcpApprovalRequest)`. + */ + fun addItem(mcpApprovalRequest: ResponseInputItem.McpApprovalRequest) = apply { + body.addItem(mcpApprovalRequest) + } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofMcpApprovalResponse(mcpApprovalResponse)`. + */ + fun addItem(mcpApprovalResponse: ResponseInputItem.McpApprovalResponse) = apply { + body.addItem(mcpApprovalResponse) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofMcpCall(mcpCall)`. */ + fun addItem(mcpCall: ResponseInputItem.McpCall) = apply { body.addItem(mcpCall) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofCustomToolCallOutput(customToolCallOutput)`. + */ + fun addItem(customToolCallOutput: ResponseCustomToolCallOutput) = apply { + body.addItem(customToolCallOutput) + } + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofCustomToolCall(customToolCall)`. + */ + fun addItem(customToolCall: ResponseCustomToolCall) = apply { body.addItem(customToolCall) } + + /** Alias for calling [addItem] with `ResponseInputItem.ofItemReference(itemReference)`. */ + fun addItem(itemReference: ResponseInputItem.ItemReference) = apply { + body.addItem(itemReference) + } + + /** + * Alias for calling [addItem] with the following: + * ```java + * ResponseInputItem.ItemReference.builder() + * .type(ResponseInputItem.ItemReference.Type.ITEM_REFERENCE) + * .id(id) + * .build() + * ``` + */ + fun addItemReferenceItem(id: String) = apply { body.addItemReferenceItem(id) } + + /** + * Set of 16 key-value pairs that can be attached to an object. Useful for storing + * additional information about the object in a structured format. + */ + fun metadata(metadata: Metadata?) = apply { body.metadata(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 { body.metadata(metadata) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [ConversationCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): ConversationCreateParams = + ConversationCreateParams( + body.build(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Body = body + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + /** Create a conversation */ + class Body + private constructor( + private val items: JsonField>, + private val metadata: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("items") + @ExcludeMissing + items: JsonField> = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + metadata: JsonField = JsonMissing.of(), + ) : this(items, metadata, mutableMapOf()) + + /** + * Initial items to include in the conversation context. You may add up to 20 items at a + * time. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun items(): Optional> = items.getOptional("items") + + /** + * Set of 16 key-value pairs that can be attached to an object. Useful for storing + * additional information about the object in a structured format. + * + * @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") + + /** + * Returns the raw JSON value of [items]. + * + * Unlike [items], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("items") + @ExcludeMissing + fun _items(): JsonField> = items + + /** + * 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 + + @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 [Body]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var items: JsonField>? = null + private var metadata: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + items = body.items.map { it.toMutableList() } + metadata = body.metadata + additionalProperties = body.additionalProperties.toMutableMap() + } + + /** + * Initial items to include in the conversation context. You may add up to 20 items at a + * time. + */ + fun items(items: List?) = items(JsonField.ofNullable(items)) + + /** Alias for calling [Builder.items] with `items.orElse(null)`. */ + fun items(items: Optional>) = items(items.getOrNull()) + + /** + * Sets [Builder.items] to an arbitrary JSON value. + * + * You should usually call [Builder.items] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun items(items: JsonField>) = apply { + this.items = items.map { it.toMutableList() } + } + + /** + * Adds a single [ResponseInputItem] to [items]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addItem(item: ResponseInputItem) = apply { + items = + (items ?: JsonField.of(mutableListOf())).also { + checkKnown("items", it).add(item) + } + } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofEasyInputMessage(easyInputMessage)`. + */ + fun addItem(easyInputMessage: EasyInputMessage) = + addItem(ResponseInputItem.ofEasyInputMessage(easyInputMessage)) + + /** Alias for calling [addItem] with `ResponseInputItem.ofMessage(message)`. */ + fun addItem(message: ResponseInputItem.Message) = + addItem(ResponseInputItem.ofMessage(message)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofResponseOutputMessage(responseOutputMessage)`. + */ + fun addItem(responseOutputMessage: ResponseOutputMessage) = + addItem(ResponseInputItem.ofResponseOutputMessage(responseOutputMessage)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofFileSearchCall(fileSearchCall)`. + */ + fun addItem(fileSearchCall: ResponseFileSearchToolCall) = + addItem(ResponseInputItem.ofFileSearchCall(fileSearchCall)) + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofComputerCall(computerCall)`. + */ + fun addItem(computerCall: ResponseComputerToolCall) = + addItem(ResponseInputItem.ofComputerCall(computerCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofComputerCallOutput(computerCallOutput)`. + */ + fun addItem(computerCallOutput: ResponseInputItem.ComputerCallOutput) = + addItem(ResponseInputItem.ofComputerCallOutput(computerCallOutput)) + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofWebSearchCall(webSearchCall)`. + */ + fun addItem(webSearchCall: ResponseFunctionWebSearch) = + addItem(ResponseInputItem.ofWebSearchCall(webSearchCall)) + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofFunctionCall(functionCall)`. + */ + fun addItem(functionCall: ResponseFunctionToolCall) = + addItem(ResponseInputItem.ofFunctionCall(functionCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofFunctionCallOutput(functionCallOutput)`. + */ + fun addItem(functionCallOutput: ResponseInputItem.FunctionCallOutput) = + addItem(ResponseInputItem.ofFunctionCallOutput(functionCallOutput)) + + /** Alias for calling [addItem] with `ResponseInputItem.ofReasoning(reasoning)`. */ + fun addItem(reasoning: ResponseReasoningItem) = + addItem(ResponseInputItem.ofReasoning(reasoning)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofImageGenerationCall(imageGenerationCall)`. + */ + fun addItem(imageGenerationCall: ResponseInputItem.ImageGenerationCall) = + addItem(ResponseInputItem.ofImageGenerationCall(imageGenerationCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofCodeInterpreterCall(codeInterpreterCall)`. + */ + fun addItem(codeInterpreterCall: ResponseCodeInterpreterToolCall) = + addItem(ResponseInputItem.ofCodeInterpreterCall(codeInterpreterCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofLocalShellCall(localShellCall)`. + */ + fun addItem(localShellCall: ResponseInputItem.LocalShellCall) = + addItem(ResponseInputItem.ofLocalShellCall(localShellCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofLocalShellCallOutput(localShellCallOutput)`. + */ + fun addItem(localShellCallOutput: ResponseInputItem.LocalShellCallOutput) = + addItem(ResponseInputItem.ofLocalShellCallOutput(localShellCallOutput)) + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofMcpListTools(mcpListTools)`. + */ + fun addItem(mcpListTools: ResponseInputItem.McpListTools) = + addItem(ResponseInputItem.ofMcpListTools(mcpListTools)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofMcpApprovalRequest(mcpApprovalRequest)`. + */ + fun addItem(mcpApprovalRequest: ResponseInputItem.McpApprovalRequest) = + addItem(ResponseInputItem.ofMcpApprovalRequest(mcpApprovalRequest)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofMcpApprovalResponse(mcpApprovalResponse)`. + */ + fun addItem(mcpApprovalResponse: ResponseInputItem.McpApprovalResponse) = + addItem(ResponseInputItem.ofMcpApprovalResponse(mcpApprovalResponse)) + + /** Alias for calling [addItem] with `ResponseInputItem.ofMcpCall(mcpCall)`. */ + fun addItem(mcpCall: ResponseInputItem.McpCall) = + addItem(ResponseInputItem.ofMcpCall(mcpCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofCustomToolCallOutput(customToolCallOutput)`. + */ + fun addItem(customToolCallOutput: ResponseCustomToolCallOutput) = + addItem(ResponseInputItem.ofCustomToolCallOutput(customToolCallOutput)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofCustomToolCall(customToolCall)`. + */ + fun addItem(customToolCall: ResponseCustomToolCall) = + addItem(ResponseInputItem.ofCustomToolCall(customToolCall)) + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofItemReference(itemReference)`. + */ + fun addItem(itemReference: ResponseInputItem.ItemReference) = + addItem(ResponseInputItem.ofItemReference(itemReference)) + + /** + * Alias for calling [addItem] with the following: + * ```java + * ResponseInputItem.ItemReference.builder() + * .type(ResponseInputItem.ItemReference.Type.ITEM_REFERENCE) + * .id(id) + * .build() + * ``` + */ + fun addItemReferenceItem(id: String) = + addItem( + ResponseInputItem.ItemReference.builder() + .type(ResponseInputItem.ItemReference.Type.ITEM_REFERENCE) + .id(id) + .build() + ) + + /** + * Set of 16 key-value pairs that can be attached to an object. Useful for storing + * additional information about the object in a structured format. + */ + 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 } + + 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 [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Body = + Body( + (items ?: JsonMissing.of()).map { it.toImmutable() }, + metadata, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Body = apply { + if (validated) { + return@apply + } + + items().ifPresent { it.forEach { it.validate() } } + metadata().ifPresent { 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 = + (items.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (metadata.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + items == other.items && + metadata == other.metadata && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(items, metadata, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Body{items=$items, metadata=$metadata, additionalProperties=$additionalProperties}" + } + + /** + * 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}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConversationCreateParams && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams) + + override fun toString() = + "ConversationCreateParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationDeleteParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationDeleteParams.kt new file mode 100644 index 000000000..37d8342ac --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationDeleteParams.kt @@ -0,0 +1,236 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.openai.core.JsonValue +import com.openai.core.Params +import com.openai.core.http.Headers +import com.openai.core.http.QueryParams +import com.openai.core.toImmutable +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Delete a conversation with the given ID. */ +class ConversationDeleteParams +private constructor( + private val conversationId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun conversationId(): Optional = Optional.ofNullable(conversationId) + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): ConversationDeleteParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [ConversationDeleteParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConversationDeleteParams]. */ + class Builder internal constructor() { + + private var conversationId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(conversationDeleteParams: ConversationDeleteParams) = apply { + conversationId = conversationDeleteParams.conversationId + additionalHeaders = conversationDeleteParams.additionalHeaders.toBuilder() + additionalQueryParams = conversationDeleteParams.additionalQueryParams.toBuilder() + additionalBodyProperties = + conversationDeleteParams.additionalBodyProperties.toMutableMap() + } + + fun conversationId(conversationId: String?) = apply { this.conversationId = conversationId } + + /** Alias for calling [Builder.conversationId] with `conversationId.orElse(null)`. */ + fun conversationId(conversationId: Optional) = + conversationId(conversationId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [ConversationDeleteParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): ConversationDeleteParams = + ConversationDeleteParams( + conversationId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Optional> = + Optional.ofNullable(additionalBodyProperties.ifEmpty { null }) + + fun _pathParam(index: Int): String = + when (index) { + 0 -> conversationId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConversationDeleteParams && + conversationId == other.conversationId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash( + conversationId, + additionalHeaders, + additionalQueryParams, + additionalBodyProperties, + ) + + override fun toString() = + "ConversationDeleteParams{conversationId=$conversationId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationDeleted.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationDeleted.kt new file mode 100644 index 000000000..e2b584698 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationDeleted.kt @@ -0,0 +1,241 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +class ConversationDeleted +private constructor( + private val id: JsonField, + private val deleted: JsonField, + private val object_: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("deleted") @ExcludeMissing deleted: JsonField = JsonMissing.of(), + @JsonProperty("object") @ExcludeMissing object_: JsonValue = JsonMissing.of(), + ) : this(id, deleted, object_, mutableMapOf()) + + /** + * @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 id(): String = id.getRequired("id") + + /** + * @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 deleted(): Boolean = deleted.getRequired("deleted") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("conversation.deleted") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). + */ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonValue = object_ + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [deleted]. + * + * Unlike [deleted], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("deleted") @ExcludeMissing fun _deleted(): JsonField = deleted + + @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 [ConversationDeleted]. + * + * The following fields are required: + * ```java + * .id() + * .deleted() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConversationDeleted]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var deleted: JsonField? = null + private var object_: JsonValue = JsonValue.from("conversation.deleted") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(conversationDeleted: ConversationDeleted) = apply { + id = conversationDeleted.id + deleted = conversationDeleted.deleted + object_ = conversationDeleted.object_ + additionalProperties = conversationDeleted.additionalProperties.toMutableMap() + } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun deleted(deleted: Boolean) = deleted(JsonField.of(deleted)) + + /** + * Sets [Builder.deleted] to an arbitrary JSON value. + * + * You should usually call [Builder.deleted] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun deleted(deleted: JsonField) = apply { this.deleted = deleted } + + /** + * 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("conversation.deleted") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun object_(object_: JsonValue) = apply { this.object_ = object_ } + + 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 [ConversationDeleted]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .deleted() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConversationDeleted = + ConversationDeleted( + checkRequired("id", id), + checkRequired("deleted", deleted), + object_, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConversationDeleted = apply { + if (validated) { + return@apply + } + + id() + deleted() + _object_().let { + if (it != JsonValue.from("conversation.deleted")) { + throw OpenAIInvalidDataException("'object_' is invalid, received $it") + } + } + 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 (id.asKnown().isPresent) 1 else 0) + + (if (deleted.asKnown().isPresent) 1 else 0) + + object_.let { if (it == JsonValue.from("conversation.deleted")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConversationDeleted && + id == other.id && + deleted == other.deleted && + object_ == other.object_ && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, deleted, object_, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConversationDeleted{id=$id, deleted=$deleted, object_=$object_, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationDeletedResource.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationDeletedResource.kt new file mode 100644 index 000000000..cd53ff5fb --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationDeletedResource.kt @@ -0,0 +1,241 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +class ConversationDeletedResource +private constructor( + private val id: JsonField, + private val deleted: JsonField, + private val object_: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("deleted") @ExcludeMissing deleted: JsonField = JsonMissing.of(), + @JsonProperty("object") @ExcludeMissing object_: JsonValue = JsonMissing.of(), + ) : this(id, deleted, object_, mutableMapOf()) + + /** + * @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 id(): String = id.getRequired("id") + + /** + * @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 deleted(): Boolean = deleted.getRequired("deleted") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("conversation.deleted") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). + */ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonValue = object_ + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [deleted]. + * + * Unlike [deleted], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("deleted") @ExcludeMissing fun _deleted(): JsonField = deleted + + @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 [ConversationDeletedResource]. + * + * The following fields are required: + * ```java + * .id() + * .deleted() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConversationDeletedResource]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var deleted: JsonField? = null + private var object_: JsonValue = JsonValue.from("conversation.deleted") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(conversationDeletedResource: ConversationDeletedResource) = apply { + id = conversationDeletedResource.id + deleted = conversationDeletedResource.deleted + object_ = conversationDeletedResource.object_ + additionalProperties = conversationDeletedResource.additionalProperties.toMutableMap() + } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun deleted(deleted: Boolean) = deleted(JsonField.of(deleted)) + + /** + * Sets [Builder.deleted] to an arbitrary JSON value. + * + * You should usually call [Builder.deleted] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun deleted(deleted: JsonField) = apply { this.deleted = deleted } + + /** + * 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("conversation.deleted") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun object_(object_: JsonValue) = apply { this.object_ = object_ } + + 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 [ConversationDeletedResource]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .deleted() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConversationDeletedResource = + ConversationDeletedResource( + checkRequired("id", id), + checkRequired("deleted", deleted), + object_, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConversationDeletedResource = apply { + if (validated) { + return@apply + } + + id() + deleted() + _object_().let { + if (it != JsonValue.from("conversation.deleted")) { + throw OpenAIInvalidDataException("'object_' is invalid, received $it") + } + } + 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 (id.asKnown().isPresent) 1 else 0) + + (if (deleted.asKnown().isPresent) 1 else 0) + + object_.let { if (it == JsonValue.from("conversation.deleted")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConversationDeletedResource && + id == other.id && + deleted == other.deleted && + object_ == other.object_ && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, deleted, object_, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConversationDeletedResource{id=$id, deleted=$deleted, object_=$object_, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationRetrieveParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationRetrieveParams.kt new file mode 100644 index 000000000..2898413a6 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationRetrieveParams.kt @@ -0,0 +1,197 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.openai.core.Params +import com.openai.core.http.Headers +import com.openai.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Get a conversation with the given ID. */ +class ConversationRetrieveParams +private constructor( + private val conversationId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun conversationId(): Optional = Optional.ofNullable(conversationId) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): ConversationRetrieveParams = builder().build() + + /** + * Returns a mutable builder for constructing an instance of [ConversationRetrieveParams]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConversationRetrieveParams]. */ + class Builder internal constructor() { + + private var conversationId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(conversationRetrieveParams: ConversationRetrieveParams) = apply { + conversationId = conversationRetrieveParams.conversationId + additionalHeaders = conversationRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = conversationRetrieveParams.additionalQueryParams.toBuilder() + } + + fun conversationId(conversationId: String?) = apply { this.conversationId = conversationId } + + /** Alias for calling [Builder.conversationId] with `conversationId.orElse(null)`. */ + fun conversationId(conversationId: Optional) = + conversationId(conversationId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [ConversationRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): ConversationRetrieveParams = + ConversationRetrieveParams( + conversationId, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> conversationId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConversationRetrieveParams && + conversationId == other.conversationId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(conversationId, additionalHeaders, additionalQueryParams) + + override fun toString() = + "ConversationRetrieveParams{conversationId=$conversationId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationUpdateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationUpdateParams.kt new file mode 100644 index 000000000..294a62f67 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationUpdateParams.kt @@ -0,0 +1,562 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.Params +import com.openai.core.checkRequired +import com.openai.core.http.Headers +import com.openai.core.http.QueryParams +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Update a conversation's metadata with the given ID. */ +class ConversationUpdateParams +private constructor( + private val conversationId: String?, + private val body: Body, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun conversationId(): Optional = Optional.ofNullable(conversationId) + + /** + * 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 or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun metadata(): Metadata = body.metadata() + + /** + * Returns the raw JSON value of [metadata]. + * + * Unlike [metadata], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _metadata(): JsonField = body._metadata() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [ConversationUpdateParams]. + * + * The following fields are required: + * ```java + * .metadata() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConversationUpdateParams]. */ + class Builder internal constructor() { + + private var conversationId: String? = null + private var body: Body.Builder = Body.builder() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(conversationUpdateParams: ConversationUpdateParams) = apply { + conversationId = conversationUpdateParams.conversationId + body = conversationUpdateParams.body.toBuilder() + additionalHeaders = conversationUpdateParams.additionalHeaders.toBuilder() + additionalQueryParams = conversationUpdateParams.additionalQueryParams.toBuilder() + } + + fun conversationId(conversationId: String?) = apply { this.conversationId = conversationId } + + /** Alias for calling [Builder.conversationId] with `conversationId.orElse(null)`. */ + fun conversationId(conversationId: Optional) = + conversationId(conversationId.getOrNull()) + + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [metadata] + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + /** + * 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) = apply { body.metadata(metadata) } + + /** + * 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 { body.metadata(metadata) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [ConversationUpdateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .metadata() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConversationUpdateParams = + ConversationUpdateParams( + conversationId, + body.build(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Body = body + + fun _pathParam(index: Int): String = + when (index) { + 0 -> conversationId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + class Body + private constructor( + private val metadata: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("metadata") + @ExcludeMissing + metadata: JsonField = JsonMissing.of() + ) : this(metadata, mutableMapOf()) + + /** + * 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 or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun metadata(): Metadata = metadata.getRequired("metadata") + + /** + * 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 + + @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 [Body]. + * + * The following fields are required: + * ```java + * .metadata() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var metadata: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + metadata = body.metadata + additionalProperties = body.additionalProperties.toMutableMap() + } + + /** + * 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.of(metadata)) + + /** + * 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 } + + 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 [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .metadata() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Body = + Body(checkRequired("metadata", metadata), additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Body = apply { + if (validated) { + return@apply + } + + metadata().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 = (metadata.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + metadata == other.metadata && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(metadata, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Body{metadata=$metadata, additionalProperties=$additionalProperties}" + } + + /** + * 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}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConversationUpdateParams && + conversationId == other.conversationId && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(conversationId, body, additionalHeaders, additionalQueryParams) + + override fun toString() = + "ConversationUpdateParams{conversationId=$conversationId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/FileCitationBody.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/FileCitationBody.kt new file mode 100644 index 000000000..e82bfe5df --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/FileCitationBody.kt @@ -0,0 +1,287 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +class FileCitationBody +private constructor( + private val fileId: JsonField, + private val filename: JsonField, + private val index: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("file_id") @ExcludeMissing fileId: JsonField = JsonMissing.of(), + @JsonProperty("filename") @ExcludeMissing filename: JsonField = JsonMissing.of(), + @JsonProperty("index") @ExcludeMissing index: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(fileId, filename, index, type, mutableMapOf()) + + /** + * The ID of the file. + * + * @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 fileId(): String = fileId.getRequired("file_id") + + /** + * The filename of the file cited. + * + * @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 filename(): String = filename.getRequired("filename") + + /** + * The index of the file in the list of files. + * + * @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 index(): Long = index.getRequired("index") + + /** + * The type of the file citation. Always `file_citation`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("file_citation") + * ``` + * + * 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 + + /** + * Returns the raw JSON value of [fileId]. + * + * Unlike [fileId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId + + /** + * Returns the raw JSON value of [filename]. + * + * Unlike [filename], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("filename") @ExcludeMissing fun _filename(): JsonField = filename + + /** + * Returns the raw JSON value of [index]. + * + * Unlike [index], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("index") @ExcludeMissing fun _index(): JsonField = index + + @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 [FileCitationBody]. + * + * The following fields are required: + * ```java + * .fileId() + * .filename() + * .index() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [FileCitationBody]. */ + class Builder internal constructor() { + + private var fileId: JsonField? = null + private var filename: JsonField? = null + private var index: JsonField? = null + private var type: JsonValue = JsonValue.from("file_citation") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(fileCitationBody: FileCitationBody) = apply { + fileId = fileCitationBody.fileId + filename = fileCitationBody.filename + index = fileCitationBody.index + type = fileCitationBody.type + additionalProperties = fileCitationBody.additionalProperties.toMutableMap() + } + + /** The ID of the file. */ + fun fileId(fileId: String) = fileId(JsonField.of(fileId)) + + /** + * Sets [Builder.fileId] to an arbitrary JSON value. + * + * You should usually call [Builder.fileId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } + + /** The filename of the file cited. */ + fun filename(filename: String) = filename(JsonField.of(filename)) + + /** + * Sets [Builder.filename] to an arbitrary JSON value. + * + * You should usually call [Builder.filename] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun filename(filename: JsonField) = apply { this.filename = filename } + + /** The index of the file in the list of files. */ + fun index(index: Long) = index(JsonField.of(index)) + + /** + * Sets [Builder.index] to an arbitrary JSON value. + * + * You should usually call [Builder.index] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun index(index: JsonField) = apply { this.index = index } + + /** + * 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("file_citation") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [FileCitationBody]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .fileId() + * .filename() + * .index() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): FileCitationBody = + FileCitationBody( + checkRequired("fileId", fileId), + checkRequired("filename", filename), + checkRequired("index", index), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): FileCitationBody = apply { + if (validated) { + return@apply + } + + fileId() + filename() + index() + _type().let { + if (it != JsonValue.from("file_citation")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 (fileId.asKnown().isPresent) 1 else 0) + + (if (filename.asKnown().isPresent) 1 else 0) + + (if (index.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("file_citation")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FileCitationBody && + fileId == other.fileId && + filename == other.filename && + index == other.index && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(fileId, filename, index, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "FileCitationBody{fileId=$fileId, filename=$filename, index=$index, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/InputFileContent.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/InputFileContent.kt new file mode 100644 index 000000000..428456c98 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/InputFileContent.kt @@ -0,0 +1,288 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class InputFileContent +private constructor( + private val fileId: JsonField, + private val type: JsonValue, + private val fileUrl: JsonField, + private val filename: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("file_id") @ExcludeMissing fileId: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("file_url") @ExcludeMissing fileUrl: JsonField = JsonMissing.of(), + @JsonProperty("filename") @ExcludeMissing filename: JsonField = JsonMissing.of(), + ) : this(fileId, type, fileUrl, filename, mutableMapOf()) + + /** + * The ID of the file to be sent to the model. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun fileId(): Optional = fileId.getOptional("file_id") + + /** + * The type of the input item. Always `input_file`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("input_file") + * ``` + * + * 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 + + /** + * The URL of the file to be sent to the model. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun fileUrl(): Optional = fileUrl.getOptional("file_url") + + /** + * The name of the file to be sent to the model. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun filename(): Optional = filename.getOptional("filename") + + /** + * Returns the raw JSON value of [fileId]. + * + * Unlike [fileId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId + + /** + * Returns the raw JSON value of [fileUrl]. + * + * Unlike [fileUrl], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("file_url") @ExcludeMissing fun _fileUrl(): JsonField = fileUrl + + /** + * Returns the raw JSON value of [filename]. + * + * Unlike [filename], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("filename") @ExcludeMissing fun _filename(): JsonField = filename + + @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 [InputFileContent]. + * + * The following fields are required: + * ```java + * .fileId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [InputFileContent]. */ + class Builder internal constructor() { + + private var fileId: JsonField? = null + private var type: JsonValue = JsonValue.from("input_file") + private var fileUrl: JsonField = JsonMissing.of() + private var filename: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(inputFileContent: InputFileContent) = apply { + fileId = inputFileContent.fileId + type = inputFileContent.type + fileUrl = inputFileContent.fileUrl + filename = inputFileContent.filename + additionalProperties = inputFileContent.additionalProperties.toMutableMap() + } + + /** The ID of the file to be sent to the model. */ + fun fileId(fileId: String?) = fileId(JsonField.ofNullable(fileId)) + + /** Alias for calling [Builder.fileId] with `fileId.orElse(null)`. */ + fun fileId(fileId: Optional) = fileId(fileId.getOrNull()) + + /** + * Sets [Builder.fileId] to an arbitrary JSON value. + * + * You should usually call [Builder.fileId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } + + /** + * 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("input_file") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** The URL of the file to be sent to the model. */ + fun fileUrl(fileUrl: String) = fileUrl(JsonField.of(fileUrl)) + + /** + * Sets [Builder.fileUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.fileUrl] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun fileUrl(fileUrl: JsonField) = apply { this.fileUrl = fileUrl } + + /** The name of the file to be sent to the model. */ + fun filename(filename: String) = filename(JsonField.of(filename)) + + /** + * Sets [Builder.filename] to an arbitrary JSON value. + * + * You should usually call [Builder.filename] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun filename(filename: JsonField) = apply { this.filename = filename } + + 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 [InputFileContent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .fileId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): InputFileContent = + InputFileContent( + checkRequired("fileId", fileId), + type, + fileUrl, + filename, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): InputFileContent = apply { + if (validated) { + return@apply + } + + fileId() + _type().let { + if (it != JsonValue.from("input_file")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + fileUrl() + filename() + 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 (fileId.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("input_file")) 1 else 0 } + + (if (fileUrl.asKnown().isPresent) 1 else 0) + + (if (filename.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InputFileContent && + fileId == other.fileId && + type == other.type && + fileUrl == other.fileUrl && + filename == other.filename && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(fileId, type, fileUrl, filename, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "InputFileContent{fileId=$fileId, type=$type, fileUrl=$fileUrl, filename=$filename, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/InputImageContent.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/InputImageContent.kt new file mode 100644 index 000000000..c0043c729 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/InputImageContent.kt @@ -0,0 +1,439 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.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.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class InputImageContent +private constructor( + private val detail: JsonField, + private val fileId: JsonField, + private val imageUrl: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("detail") @ExcludeMissing detail: JsonField = JsonMissing.of(), + @JsonProperty("file_id") @ExcludeMissing fileId: JsonField = JsonMissing.of(), + @JsonProperty("image_url") @ExcludeMissing imageUrl: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(detail, fileId, imageUrl, type, mutableMapOf()) + + /** + * The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. + * Defaults to `auto`. + * + * @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 detail(): Detail = detail.getRequired("detail") + + /** + * The ID of the file to be sent to the model. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun fileId(): Optional = fileId.getOptional("file_id") + + /** + * The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image + * in a data URL. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun imageUrl(): Optional = imageUrl.getOptional("image_url") + + /** + * The type of the input item. Always `input_image`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("input_image") + * ``` + * + * 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 + + /** + * Returns the raw JSON value of [detail]. + * + * Unlike [detail], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("detail") @ExcludeMissing fun _detail(): JsonField = detail + + /** + * Returns the raw JSON value of [fileId]. + * + * Unlike [fileId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId + + /** + * Returns the raw JSON value of [imageUrl]. + * + * Unlike [imageUrl], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("image_url") @ExcludeMissing fun _imageUrl(): JsonField = imageUrl + + @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 [InputImageContent]. + * + * The following fields are required: + * ```java + * .detail() + * .fileId() + * .imageUrl() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [InputImageContent]. */ + class Builder internal constructor() { + + private var detail: JsonField? = null + private var fileId: JsonField? = null + private var imageUrl: JsonField? = null + private var type: JsonValue = JsonValue.from("input_image") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(inputImageContent: InputImageContent) = apply { + detail = inputImageContent.detail + fileId = inputImageContent.fileId + imageUrl = inputImageContent.imageUrl + type = inputImageContent.type + additionalProperties = inputImageContent.additionalProperties.toMutableMap() + } + + /** + * The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. + * Defaults to `auto`. + */ + fun detail(detail: Detail) = detail(JsonField.of(detail)) + + /** + * Sets [Builder.detail] to an arbitrary JSON value. + * + * You should usually call [Builder.detail] with a well-typed [Detail] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun detail(detail: JsonField) = apply { this.detail = detail } + + /** The ID of the file to be sent to the model. */ + fun fileId(fileId: String?) = fileId(JsonField.ofNullable(fileId)) + + /** Alias for calling [Builder.fileId] with `fileId.orElse(null)`. */ + fun fileId(fileId: Optional) = fileId(fileId.getOrNull()) + + /** + * Sets [Builder.fileId] to an arbitrary JSON value. + * + * You should usually call [Builder.fileId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } + + /** + * The URL of the image to be sent to the model. A fully qualified URL or base64 encoded + * image in a data URL. + */ + fun imageUrl(imageUrl: String?) = imageUrl(JsonField.ofNullable(imageUrl)) + + /** Alias for calling [Builder.imageUrl] with `imageUrl.orElse(null)`. */ + fun imageUrl(imageUrl: Optional) = imageUrl(imageUrl.getOrNull()) + + /** + * Sets [Builder.imageUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.imageUrl] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun imageUrl(imageUrl: JsonField) = apply { this.imageUrl = imageUrl } + + /** + * 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("input_image") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [InputImageContent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .detail() + * .fileId() + * .imageUrl() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): InputImageContent = + InputImageContent( + checkRequired("detail", detail), + checkRequired("fileId", fileId), + checkRequired("imageUrl", imageUrl), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): InputImageContent = apply { + if (validated) { + return@apply + } + + detail().validate() + fileId() + imageUrl() + _type().let { + if (it != JsonValue.from("input_image")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 = + (detail.asKnown().getOrNull()?.validity() ?: 0) + + (if (fileId.asKnown().isPresent) 1 else 0) + + (if (imageUrl.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("input_image")) 1 else 0 } + + /** + * The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. + * Defaults to `auto`. + */ + class Detail @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 LOW = of("low") + + @JvmField val HIGH = of("high") + + @JvmField val AUTO = of("auto") + + @JvmStatic fun of(value: String) = Detail(JsonField.of(value)) + } + + /** An enum containing [Detail]'s known values. */ + enum class Known { + LOW, + HIGH, + AUTO, + } + + /** + * An enum containing [Detail]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Detail] 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 { + LOW, + HIGH, + AUTO, + /** An enum member indicating that [Detail] 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) { + LOW -> Value.LOW + HIGH -> Value.HIGH + AUTO -> Value.AUTO + 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) { + LOW -> Known.LOW + HIGH -> Known.HIGH + AUTO -> Known.AUTO + else -> throw OpenAIInvalidDataException("Unknown Detail: $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(): Detail = 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 Detail && 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 InputImageContent && + detail == other.detail && + fileId == other.fileId && + imageUrl == other.imageUrl && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(detail, fileId, imageUrl, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "InputImageContent{detail=$detail, fileId=$fileId, imageUrl=$imageUrl, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/InputTextContent.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/InputTextContent.kt new file mode 100644 index 000000000..9b45525a0 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/InputTextContent.kt @@ -0,0 +1,209 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +class InputTextContent +private constructor( + private val text: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("text") @ExcludeMissing text: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(text, type, mutableMapOf()) + + /** + * The text input to the model. + * + * @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 text(): String = text.getRequired("text") + + /** + * The type of the input item. Always `input_text`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("input_text") + * ``` + * + * 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 + + /** + * 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 + + @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 [InputTextContent]. + * + * The following fields are required: + * ```java + * .text() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [InputTextContent]. */ + class Builder internal constructor() { + + private var text: JsonField? = null + private var type: JsonValue = JsonValue.from("input_text") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(inputTextContent: InputTextContent) = apply { + text = inputTextContent.text + type = inputTextContent.type + additionalProperties = inputTextContent.additionalProperties.toMutableMap() + } + + /** The text input to the model. */ + fun text(text: String) = text(JsonField.of(text)) + + /** + * Sets [Builder.text] to an arbitrary JSON value. + * + * You should usually call [Builder.text] with a well-typed [String] 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 } + + /** + * 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("input_text") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [InputTextContent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .text() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): InputTextContent = + InputTextContent(checkRequired("text", text), type, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): InputTextContent = apply { + if (validated) { + return@apply + } + + text() + _type().let { + if (it != JsonValue.from("input_text")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 (text.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("input_text")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InputTextContent && + text == other.text && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(text, type, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "InputTextContent{text=$text, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/LobProb.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/LobProb.kt new file mode 100644 index 000000000..af2ac367c --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/LobProb.kt @@ -0,0 +1,307 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkKnown +import com.openai.core.checkRequired +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +class LobProb +private constructor( + private val token: JsonField, + private val bytes: JsonField>, + private val logprob: JsonField, + private val topLogprobs: JsonField>, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("token") @ExcludeMissing token: JsonField = JsonMissing.of(), + @JsonProperty("bytes") @ExcludeMissing bytes: JsonField> = JsonMissing.of(), + @JsonProperty("logprob") @ExcludeMissing logprob: JsonField = JsonMissing.of(), + @JsonProperty("top_logprobs") + @ExcludeMissing + topLogprobs: JsonField> = JsonMissing.of(), + ) : this(token, bytes, logprob, topLogprobs, mutableMapOf()) + + /** + * @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 token(): String = token.getRequired("token") + + /** + * @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 bytes(): List = bytes.getRequired("bytes") + + /** + * @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 logprob(): Double = logprob.getRequired("logprob") + + /** + * @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 topLogprobs(): List = topLogprobs.getRequired("top_logprobs") + + /** + * Returns the raw JSON value of [token]. + * + * Unlike [token], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("token") @ExcludeMissing fun _token(): JsonField = token + + /** + * Returns the raw JSON value of [bytes]. + * + * Unlike [bytes], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("bytes") @ExcludeMissing fun _bytes(): JsonField> = bytes + + /** + * Returns the raw JSON value of [logprob]. + * + * Unlike [logprob], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("logprob") @ExcludeMissing fun _logprob(): JsonField = logprob + + /** + * 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 + + @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 [LobProb]. + * + * The following fields are required: + * ```java + * .token() + * .bytes() + * .logprob() + * .topLogprobs() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LobProb]. */ + class Builder internal constructor() { + + private var token: JsonField? = null + private var bytes: JsonField>? = null + private var logprob: JsonField? = null + private var topLogprobs: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(lobProb: LobProb) = apply { + token = lobProb.token + bytes = lobProb.bytes.map { it.toMutableList() } + logprob = lobProb.logprob + topLogprobs = lobProb.topLogprobs.map { it.toMutableList() } + additionalProperties = lobProb.additionalProperties.toMutableMap() + } + + fun token(token: String) = token(JsonField.of(token)) + + /** + * Sets [Builder.token] to an arbitrary JSON value. + * + * You should usually call [Builder.token] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun token(token: JsonField) = apply { this.token = token } + + fun bytes(bytes: List) = bytes(JsonField.of(bytes)) + + /** + * Sets [Builder.bytes] to an arbitrary JSON value. + * + * You should usually call [Builder.bytes] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun bytes(bytes: JsonField>) = apply { + this.bytes = bytes.map { it.toMutableList() } + } + + /** + * Adds a single [Long] to [bytes]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addByte(byte_: Long) = apply { + bytes = + (bytes ?: JsonField.of(mutableListOf())).also { checkKnown("bytes", it).add(byte_) } + } + + fun logprob(logprob: Double) = logprob(JsonField.of(logprob)) + + /** + * Sets [Builder.logprob] to an arbitrary JSON value. + * + * You should usually call [Builder.logprob] with a well-typed [Double] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun logprob(logprob: JsonField) = apply { this.logprob = logprob } + + fun topLogprobs(topLogprobs: List) = topLogprobs(JsonField.of(topLogprobs)) + + /** + * Sets [Builder.topLogprobs] to an arbitrary JSON value. + * + * You should usually call [Builder.topLogprobs] with a well-typed `List` 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.map { it.toMutableList() } + } + + /** + * Adds a single [TopLogProb] to [topLogprobs]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTopLogprob(topLogprob: TopLogProb) = apply { + topLogprobs = + (topLogprobs ?: JsonField.of(mutableListOf())).also { + checkKnown("topLogprobs", it).add(topLogprob) + } + } + + 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 [LobProb]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .token() + * .bytes() + * .logprob() + * .topLogprobs() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): LobProb = + LobProb( + checkRequired("token", token), + checkRequired("bytes", bytes).map { it.toImmutable() }, + checkRequired("logprob", logprob), + checkRequired("topLogprobs", topLogprobs).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): LobProb = apply { + if (validated) { + return@apply + } + + token() + bytes() + logprob() + topLogprobs().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 = + (if (token.asKnown().isPresent) 1 else 0) + + (bytes.asKnown().getOrNull()?.size ?: 0) + + (if (logprob.asKnown().isPresent) 1 else 0) + + (topLogprobs.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is LobProb && + token == other.token && + bytes == other.bytes && + logprob == other.logprob && + topLogprobs == other.topLogprobs && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(token, bytes, logprob, topLogprobs, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "LobProb{token=$token, bytes=$bytes, logprob=$logprob, topLogprobs=$topLogprobs, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/Message.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/Message.kt new file mode 100644 index 000000000..f9fdc5a1f --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/Message.kt @@ -0,0 +1,1097 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.checkKnown +import com.openai.core.checkRequired +import com.openai.core.getOrThrow +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class Message +private constructor( + private val id: JsonField, + private val content: JsonField>, + private val role: JsonField, + private val status: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("content") + @ExcludeMissing + content: JsonField> = JsonMissing.of(), + @JsonProperty("role") @ExcludeMissing role: JsonField = JsonMissing.of(), + @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(id, content, role, status, type, mutableMapOf()) + + /** + * The unique ID of the message. + * + * @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 id(): String = id.getRequired("id") + + /** + * The content of the message + * + * @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 content(): List = content.getRequired("content") + + /** + * The role of the message. One of `unknown`, `user`, `assistant`, `system`, `critic`, + * `discriminator`, `developer`, or `tool`. + * + * @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 role(): Role = role.getRequired("role") + + /** + * The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items + * are returned via API. + * + * @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 status(): Status = status.getRequired("status") + + /** + * The type of the message. Always set to `message`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("message") + * ``` + * + * 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 + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [content]. + * + * Unlike [content], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("content") @ExcludeMissing fun _content(): JsonField> = content + + /** + * Returns the raw JSON value of [role]. + * + * Unlike [role], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("role") @ExcludeMissing fun _role(): JsonField = role + + /** + * Returns the raw JSON value of [status]. + * + * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + + @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 [Message]. + * + * The following fields are required: + * ```java + * .id() + * .content() + * .role() + * .status() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Message]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var content: JsonField>? = null + private var role: JsonField? = null + private var status: JsonField? = null + private var type: JsonValue = JsonValue.from("message") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(message: Message) = apply { + id = message.id + content = message.content.map { it.toMutableList() } + role = message.role + status = message.status + type = message.type + additionalProperties = message.additionalProperties.toMutableMap() + } + + /** The unique ID of the message. */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** The content of the message */ + fun content(content: List) = content(JsonField.of(content)) + + /** + * Sets [Builder.content] to an arbitrary JSON value. + * + * You should usually call [Builder.content] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun content(content: JsonField>) = apply { + this.content = content.map { it.toMutableList() } + } + + /** + * Adds a single [Content] to [Builder.content]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addContent(content: Content) = apply { + this.content = + (this.content ?: JsonField.of(mutableListOf())).also { + checkKnown("content", it).add(content) + } + } + + /** Alias for calling [addContent] with `Content.ofInputText(inputText)`. */ + fun addContent(inputText: InputTextContent) = addContent(Content.ofInputText(inputText)) + + /** + * Alias for calling [addContent] with the following: + * ```java + * InputTextContent.builder() + * .text(text) + * .build() + * ``` + */ + fun addInputTextContent(text: String) = + addContent(InputTextContent.builder().text(text).build()) + + /** Alias for calling [addContent] with `Content.ofOutputText(outputText)`. */ + fun addContent(outputText: OutputTextContent) = addContent(Content.ofOutputText(outputText)) + + /** Alias for calling [addContent] with `Content.ofText(text)`. */ + fun addContent(text: TextContent) = addContent(Content.ofText(text)) + + /** + * Alias for calling [addContent] with the following: + * ```java + * TextContent.builder() + * .text(text) + * .build() + * ``` + */ + fun addTextContent(text: String) = addContent(TextContent.builder().text(text).build()) + + /** Alias for calling [addContent] with `Content.ofSummaryText(summaryText)`. */ + fun addContent(summaryText: SummaryTextContent) = + addContent(Content.ofSummaryText(summaryText)) + + /** + * Alias for calling [addContent] with the following: + * ```java + * SummaryTextContent.builder() + * .text(text) + * .build() + * ``` + */ + fun addSummaryTextContent(text: String) = + addContent(SummaryTextContent.builder().text(text).build()) + + /** Alias for calling [addContent] with `Content.ofRefusal(refusal)`. */ + fun addContent(refusal: RefusalContent) = addContent(Content.ofRefusal(refusal)) + + /** + * Alias for calling [addContent] with the following: + * ```java + * RefusalContent.builder() + * .refusal(refusal) + * .build() + * ``` + */ + fun addRefusalContent(refusal: String) = + addContent(RefusalContent.builder().refusal(refusal).build()) + + /** Alias for calling [addContent] with `Content.ofInputImage(inputImage)`. */ + fun addContent(inputImage: InputImageContent) = addContent(Content.ofInputImage(inputImage)) + + /** + * Alias for calling [addContent] with `Content.ofComputerScreenshot(computerScreenshot)`. + */ + fun addContent(computerScreenshot: ComputerScreenshotContent) = + addContent(Content.ofComputerScreenshot(computerScreenshot)) + + /** Alias for calling [addContent] with `Content.ofInputFile(inputFile)`. */ + fun addContent(inputFile: InputFileContent) = addContent(Content.ofInputFile(inputFile)) + + /** + * Alias for calling [addContent] with the following: + * ```java + * InputFileContent.builder() + * .fileId(fileId) + * .build() + * ``` + */ + fun addInputFileContent(fileId: String?) = + addContent(InputFileContent.builder().fileId(fileId).build()) + + /** Alias for calling [addInputFileContent] with `fileId.orElse(null)`. */ + fun addInputFileContent(fileId: Optional) = addInputFileContent(fileId.getOrNull()) + + /** + * The role of the message. One of `unknown`, `user`, `assistant`, `system`, `critic`, + * `discriminator`, `developer`, or `tool`. + */ + fun role(role: Role) = role(JsonField.of(role)) + + /** + * Sets [Builder.role] to an arbitrary JSON value. + * + * You should usually call [Builder.role] with a well-typed [Role] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun role(role: JsonField) = apply { this.role = role } + + /** + * The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when + * items are returned via API. + */ + fun status(status: Status) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [Status] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun status(status: JsonField) = apply { this.status = status } + + /** + * 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("message") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [Message]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .content() + * .role() + * .status() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Message = + Message( + checkRequired("id", id), + checkRequired("content", content).map { it.toImmutable() }, + checkRequired("role", role), + checkRequired("status", status), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Message = apply { + if (validated) { + return@apply + } + + id() + content().forEach { it.validate() } + role().validate() + status().validate() + _type().let { + if (it != JsonValue.from("message")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 (id.asKnown().isPresent) 1 else 0) + + (content.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (role.asKnown().getOrNull()?.validity() ?: 0) + + (status.asKnown().getOrNull()?.validity() ?: 0) + + type.let { if (it == JsonValue.from("message")) 1 else 0 } + + @JsonDeserialize(using = Content.Deserializer::class) + @JsonSerialize(using = Content.Serializer::class) + class Content + private constructor( + private val inputText: InputTextContent? = null, + private val outputText: OutputTextContent? = null, + private val text: TextContent? = null, + private val summaryText: SummaryTextContent? = null, + private val refusal: RefusalContent? = null, + private val inputImage: InputImageContent? = null, + private val computerScreenshot: ComputerScreenshotContent? = null, + private val inputFile: InputFileContent? = null, + private val _json: JsonValue? = null, + ) { + + fun inputText(): Optional = Optional.ofNullable(inputText) + + fun outputText(): Optional = Optional.ofNullable(outputText) + + fun text(): Optional = Optional.ofNullable(text) + + fun summaryText(): Optional = Optional.ofNullable(summaryText) + + fun refusal(): Optional = Optional.ofNullable(refusal) + + fun inputImage(): Optional = Optional.ofNullable(inputImage) + + fun computerScreenshot(): Optional = + Optional.ofNullable(computerScreenshot) + + fun inputFile(): Optional = Optional.ofNullable(inputFile) + + fun isInputText(): Boolean = inputText != null + + fun isOutputText(): Boolean = outputText != null + + fun isText(): Boolean = text != null + + fun isSummaryText(): Boolean = summaryText != null + + fun isRefusal(): Boolean = refusal != null + + fun isInputImage(): Boolean = inputImage != null + + fun isComputerScreenshot(): Boolean = computerScreenshot != null + + fun isInputFile(): Boolean = inputFile != null + + fun asInputText(): InputTextContent = inputText.getOrThrow("inputText") + + fun asOutputText(): OutputTextContent = outputText.getOrThrow("outputText") + + fun asText(): TextContent = text.getOrThrow("text") + + fun asSummaryText(): SummaryTextContent = summaryText.getOrThrow("summaryText") + + fun asRefusal(): RefusalContent = refusal.getOrThrow("refusal") + + fun asInputImage(): InputImageContent = inputImage.getOrThrow("inputImage") + + fun asComputerScreenshot(): ComputerScreenshotContent = + computerScreenshot.getOrThrow("computerScreenshot") + + fun asInputFile(): InputFileContent = inputFile.getOrThrow("inputFile") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + inputText != null -> visitor.visitInputText(inputText) + outputText != null -> visitor.visitOutputText(outputText) + text != null -> visitor.visitText(text) + summaryText != null -> visitor.visitSummaryText(summaryText) + refusal != null -> visitor.visitRefusal(refusal) + inputImage != null -> visitor.visitInputImage(inputImage) + computerScreenshot != null -> visitor.visitComputerScreenshot(computerScreenshot) + inputFile != null -> visitor.visitInputFile(inputFile) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Content = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitInputText(inputText: InputTextContent) { + inputText.validate() + } + + override fun visitOutputText(outputText: OutputTextContent) { + outputText.validate() + } + + override fun visitText(text: TextContent) { + text.validate() + } + + override fun visitSummaryText(summaryText: SummaryTextContent) { + summaryText.validate() + } + + override fun visitRefusal(refusal: RefusalContent) { + refusal.validate() + } + + override fun visitInputImage(inputImage: InputImageContent) { + inputImage.validate() + } + + override fun visitComputerScreenshot( + computerScreenshot: ComputerScreenshotContent + ) { + computerScreenshot.validate() + } + + override fun visitInputFile(inputFile: InputFileContent) { + inputFile.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 visitInputText(inputText: InputTextContent) = inputText.validity() + + override fun visitOutputText(outputText: OutputTextContent) = + outputText.validity() + + override fun visitText(text: TextContent) = text.validity() + + override fun visitSummaryText(summaryText: SummaryTextContent) = + summaryText.validity() + + override fun visitRefusal(refusal: RefusalContent) = refusal.validity() + + override fun visitInputImage(inputImage: InputImageContent) = + inputImage.validity() + + override fun visitComputerScreenshot( + computerScreenshot: ComputerScreenshotContent + ) = computerScreenshot.validity() + + override fun visitInputFile(inputFile: InputFileContent) = inputFile.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Content && + inputText == other.inputText && + outputText == other.outputText && + text == other.text && + summaryText == other.summaryText && + refusal == other.refusal && + inputImage == other.inputImage && + computerScreenshot == other.computerScreenshot && + inputFile == other.inputFile + } + + override fun hashCode(): Int = + Objects.hash( + inputText, + outputText, + text, + summaryText, + refusal, + inputImage, + computerScreenshot, + inputFile, + ) + + override fun toString(): String = + when { + inputText != null -> "Content{inputText=$inputText}" + outputText != null -> "Content{outputText=$outputText}" + text != null -> "Content{text=$text}" + summaryText != null -> "Content{summaryText=$summaryText}" + refusal != null -> "Content{refusal=$refusal}" + inputImage != null -> "Content{inputImage=$inputImage}" + computerScreenshot != null -> "Content{computerScreenshot=$computerScreenshot}" + inputFile != null -> "Content{inputFile=$inputFile}" + _json != null -> "Content{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Content") + } + + companion object { + + @JvmStatic fun ofInputText(inputText: InputTextContent) = Content(inputText = inputText) + + @JvmStatic + fun ofOutputText(outputText: OutputTextContent) = Content(outputText = outputText) + + @JvmStatic fun ofText(text: TextContent) = Content(text = text) + + @JvmStatic + fun ofSummaryText(summaryText: SummaryTextContent) = Content(summaryText = summaryText) + + @JvmStatic fun ofRefusal(refusal: RefusalContent) = Content(refusal = refusal) + + @JvmStatic + fun ofInputImage(inputImage: InputImageContent) = Content(inputImage = inputImage) + + @JvmStatic + fun ofComputerScreenshot(computerScreenshot: ComputerScreenshotContent) = + Content(computerScreenshot = computerScreenshot) + + @JvmStatic fun ofInputFile(inputFile: InputFileContent) = Content(inputFile = inputFile) + } + + /** + * An interface that defines how to map each variant of [Content] to a value of type [T]. + */ + interface Visitor { + + fun visitInputText(inputText: InputTextContent): T + + fun visitOutputText(outputText: OutputTextContent): T + + fun visitText(text: TextContent): T + + fun visitSummaryText(summaryText: SummaryTextContent): T + + fun visitRefusal(refusal: RefusalContent): T + + fun visitInputImage(inputImage: InputImageContent): T + + fun visitComputerScreenshot(computerScreenshot: ComputerScreenshotContent): T + + fun visitInputFile(inputFile: InputFileContent): T + + /** + * Maps an unknown variant of [Content] to a value of type [T]. + * + * An instance of [Content] 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 Content: $json") + } + } + + internal class Deserializer : BaseDeserializer(Content::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Content { + val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() + + when (type) { + "input_text" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Content(inputText = it, _json = json) + } ?: Content(_json = json) + } + "output_text" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Content(outputText = it, _json = json) + } ?: Content(_json = json) + } + "text" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Content(text = it, _json = json) + } ?: Content(_json = json) + } + "summary_text" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Content(summaryText = it, _json = json) + } ?: Content(_json = json) + } + "refusal" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Content(refusal = it, _json = json) + } ?: Content(_json = json) + } + "input_image" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Content(inputImage = it, _json = json) + } ?: Content(_json = json) + } + "computer_screenshot" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { Content(computerScreenshot = it, _json = json) } + ?: Content(_json = json) + } + "input_file" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Content(inputFile = it, _json = json) + } ?: Content(_json = json) + } + } + + return Content(_json = json) + } + } + + internal class Serializer : BaseSerializer(Content::class) { + + override fun serialize( + value: Content, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.inputText != null -> generator.writeObject(value.inputText) + value.outputText != null -> generator.writeObject(value.outputText) + value.text != null -> generator.writeObject(value.text) + value.summaryText != null -> generator.writeObject(value.summaryText) + value.refusal != null -> generator.writeObject(value.refusal) + value.inputImage != null -> generator.writeObject(value.inputImage) + value.computerScreenshot != null -> + generator.writeObject(value.computerScreenshot) + value.inputFile != null -> generator.writeObject(value.inputFile) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Content") + } + } + } + } + + /** + * The role of the message. One of `unknown`, `user`, `assistant`, `system`, `critic`, + * `discriminator`, `developer`, or `tool`. + */ + class Role @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 UNKNOWN = of("unknown") + + @JvmField val USER = of("user") + + @JvmField val ASSISTANT = of("assistant") + + @JvmField val SYSTEM = of("system") + + @JvmField val CRITIC = of("critic") + + @JvmField val DISCRIMINATOR = of("discriminator") + + @JvmField val DEVELOPER = of("developer") + + @JvmField val TOOL = of("tool") + + @JvmStatic fun of(value: String) = Role(JsonField.of(value)) + } + + /** An enum containing [Role]'s known values. */ + enum class Known { + UNKNOWN, + USER, + ASSISTANT, + SYSTEM, + CRITIC, + DISCRIMINATOR, + DEVELOPER, + TOOL, + } + + /** + * An enum containing [Role]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Role] 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 { + UNKNOWN, + USER, + ASSISTANT, + SYSTEM, + CRITIC, + DISCRIMINATOR, + DEVELOPER, + TOOL, + /** An enum member indicating that [Role] 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) { + UNKNOWN -> Value.UNKNOWN + USER -> Value.USER + ASSISTANT -> Value.ASSISTANT + SYSTEM -> Value.SYSTEM + CRITIC -> Value.CRITIC + DISCRIMINATOR -> Value.DISCRIMINATOR + DEVELOPER -> Value.DEVELOPER + TOOL -> Value.TOOL + 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) { + UNKNOWN -> Known.UNKNOWN + USER -> Known.USER + ASSISTANT -> Known.ASSISTANT + SYSTEM -> Known.SYSTEM + CRITIC -> Known.CRITIC + DISCRIMINATOR -> Known.DISCRIMINATOR + DEVELOPER -> Known.DEVELOPER + TOOL -> Known.TOOL + else -> throw OpenAIInvalidDataException("Unknown Role: $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(): Role = 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 Role && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items + * are returned via API. + */ + class Status @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_PROGRESS = of("in_progress") + + @JvmField val COMPLETED = of("completed") + + @JvmField val INCOMPLETE = of("incomplete") + + @JvmStatic fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + IN_PROGRESS, + COMPLETED, + INCOMPLETE, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] 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_PROGRESS, + COMPLETED, + INCOMPLETE, + /** An enum member indicating that [Status] 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_PROGRESS -> Value.IN_PROGRESS + COMPLETED -> Value.COMPLETED + INCOMPLETE -> Value.INCOMPLETE + 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_PROGRESS -> Known.IN_PROGRESS + COMPLETED -> Known.COMPLETED + INCOMPLETE -> Known.INCOMPLETE + else -> throw OpenAIInvalidDataException("Unknown Status: $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(): Status = 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 Status && 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 Message && + id == other.id && + content == other.content && + role == other.role && + status == other.status && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(id, content, role, status, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Message{id=$id, content=$content, role=$role, status=$status, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/OutputTextContent.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/OutputTextContent.kt new file mode 100644 index 000000000..1fe6ccb72 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/OutputTextContent.kt @@ -0,0 +1,558 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +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 java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class OutputTextContent +private constructor( + private val annotations: JsonField>, + private val text: JsonField, + private val type: JsonValue, + private val logprobs: JsonField>, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("annotations") + @ExcludeMissing + annotations: JsonField> = JsonMissing.of(), + @JsonProperty("text") @ExcludeMissing text: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("logprobs") + @ExcludeMissing + logprobs: JsonField> = JsonMissing.of(), + ) : this(annotations, text, type, logprobs, mutableMapOf()) + + /** + * The annotations of the text output. + * + * @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 annotations(): List = annotations.getRequired("annotations") + + /** + * The text output from the model. + * + * @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 text(): String = text.getRequired("text") + + /** + * The type of the output text. Always `output_text`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("output_text") + * ``` + * + * 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 + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun logprobs(): Optional> = logprobs.getOptional("logprobs") + + /** + * Returns the raw JSON value of [annotations]. + * + * Unlike [annotations], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("annotations") + @ExcludeMissing + fun _annotations(): JsonField> = annotations + + /** + * 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 [logprobs]. + * + * Unlike [logprobs], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("logprobs") @ExcludeMissing fun _logprobs(): JsonField> = logprobs + + @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 [OutputTextContent]. + * + * The following fields are required: + * ```java + * .annotations() + * .text() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [OutputTextContent]. */ + class Builder internal constructor() { + + private var annotations: JsonField>? = null + private var text: JsonField? = null + private var type: JsonValue = JsonValue.from("output_text") + private var logprobs: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(outputTextContent: OutputTextContent) = apply { + annotations = outputTextContent.annotations.map { it.toMutableList() } + text = outputTextContent.text + type = outputTextContent.type + logprobs = outputTextContent.logprobs.map { it.toMutableList() } + additionalProperties = outputTextContent.additionalProperties.toMutableMap() + } + + /** The annotations of the text output. */ + fun annotations(annotations: List) = annotations(JsonField.of(annotations)) + + /** + * Sets [Builder.annotations] to an arbitrary JSON value. + * + * You should usually call [Builder.annotations] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun annotations(annotations: JsonField>) = apply { + this.annotations = annotations.map { it.toMutableList() } + } + + /** + * Adds a single [Annotation] to [annotations]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAnnotation(annotation: Annotation) = apply { + annotations = + (annotations ?: JsonField.of(mutableListOf())).also { + checkKnown("annotations", it).add(annotation) + } + } + + /** Alias for calling [addAnnotation] with `Annotation.ofFileCitation(fileCitation)`. */ + fun addAnnotation(fileCitation: FileCitationBody) = + addAnnotation(Annotation.ofFileCitation(fileCitation)) + + /** Alias for calling [addAnnotation] with `Annotation.ofUrlCitation(urlCitation)`. */ + fun addAnnotation(urlCitation: UrlCitationBody) = + addAnnotation(Annotation.ofUrlCitation(urlCitation)) + + /** + * Alias for calling [addAnnotation] with + * `Annotation.ofContainerFileCitation(containerFileCitation)`. + */ + fun addAnnotation(containerFileCitation: ContainerFileCitationBody) = + addAnnotation(Annotation.ofContainerFileCitation(containerFileCitation)) + + /** The text output from the model. */ + fun text(text: String) = text(JsonField.of(text)) + + /** + * Sets [Builder.text] to an arbitrary JSON value. + * + * You should usually call [Builder.text] with a well-typed [String] 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 } + + /** + * 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("output_text") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + fun logprobs(logprobs: List) = logprobs(JsonField.of(logprobs)) + + /** + * Sets [Builder.logprobs] to an arbitrary JSON value. + * + * You should usually call [Builder.logprobs] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun logprobs(logprobs: JsonField>) = apply { + this.logprobs = logprobs.map { it.toMutableList() } + } + + /** + * Adds a single [LobProb] to [logprobs]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addLogprob(logprob: LobProb) = apply { + logprobs = + (logprobs ?: JsonField.of(mutableListOf())).also { + checkKnown("logprobs", it).add(logprob) + } + } + + 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 [OutputTextContent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .annotations() + * .text() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): OutputTextContent = + OutputTextContent( + checkRequired("annotations", annotations).map { it.toImmutable() }, + checkRequired("text", text), + type, + (logprobs ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): OutputTextContent = apply { + if (validated) { + return@apply + } + + annotations().forEach { it.validate() } + text() + _type().let { + if (it != JsonValue.from("output_text")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + logprobs().ifPresent { it.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 = + (annotations.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (text.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("output_text")) 1 else 0 } + + (logprobs.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + @JsonDeserialize(using = Annotation.Deserializer::class) + @JsonSerialize(using = Annotation.Serializer::class) + class Annotation + private constructor( + private val fileCitation: FileCitationBody? = null, + private val urlCitation: UrlCitationBody? = null, + private val containerFileCitation: ContainerFileCitationBody? = null, + private val _json: JsonValue? = null, + ) { + + fun fileCitation(): Optional = Optional.ofNullable(fileCitation) + + fun urlCitation(): Optional = Optional.ofNullable(urlCitation) + + fun containerFileCitation(): Optional = + Optional.ofNullable(containerFileCitation) + + fun isFileCitation(): Boolean = fileCitation != null + + fun isUrlCitation(): Boolean = urlCitation != null + + fun isContainerFileCitation(): Boolean = containerFileCitation != null + + fun asFileCitation(): FileCitationBody = fileCitation.getOrThrow("fileCitation") + + fun asUrlCitation(): UrlCitationBody = urlCitation.getOrThrow("urlCitation") + + fun asContainerFileCitation(): ContainerFileCitationBody = + containerFileCitation.getOrThrow("containerFileCitation") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + fileCitation != null -> visitor.visitFileCitation(fileCitation) + urlCitation != null -> visitor.visitUrlCitation(urlCitation) + containerFileCitation != null -> + visitor.visitContainerFileCitation(containerFileCitation) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Annotation = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitFileCitation(fileCitation: FileCitationBody) { + fileCitation.validate() + } + + override fun visitUrlCitation(urlCitation: UrlCitationBody) { + urlCitation.validate() + } + + override fun visitContainerFileCitation( + containerFileCitation: ContainerFileCitationBody + ) { + containerFileCitation.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 visitFileCitation(fileCitation: FileCitationBody) = + fileCitation.validity() + + override fun visitUrlCitation(urlCitation: UrlCitationBody) = + urlCitation.validity() + + override fun visitContainerFileCitation( + containerFileCitation: ContainerFileCitationBody + ) = containerFileCitation.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Annotation && + fileCitation == other.fileCitation && + urlCitation == other.urlCitation && + containerFileCitation == other.containerFileCitation + } + + override fun hashCode(): Int = + Objects.hash(fileCitation, urlCitation, containerFileCitation) + + override fun toString(): String = + when { + fileCitation != null -> "Annotation{fileCitation=$fileCitation}" + urlCitation != null -> "Annotation{urlCitation=$urlCitation}" + containerFileCitation != null -> + "Annotation{containerFileCitation=$containerFileCitation}" + _json != null -> "Annotation{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Annotation") + } + + companion object { + + @JvmStatic + fun ofFileCitation(fileCitation: FileCitationBody) = + Annotation(fileCitation = fileCitation) + + @JvmStatic + fun ofUrlCitation(urlCitation: UrlCitationBody) = Annotation(urlCitation = urlCitation) + + @JvmStatic + fun ofContainerFileCitation(containerFileCitation: ContainerFileCitationBody) = + Annotation(containerFileCitation = containerFileCitation) + } + + /** + * An interface that defines how to map each variant of [Annotation] to a value of type [T]. + */ + interface Visitor { + + fun visitFileCitation(fileCitation: FileCitationBody): T + + fun visitUrlCitation(urlCitation: UrlCitationBody): T + + fun visitContainerFileCitation(containerFileCitation: ContainerFileCitationBody): T + + /** + * Maps an unknown variant of [Annotation] to a value of type [T]. + * + * An instance of [Annotation] 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 Annotation: $json") + } + } + + internal class Deserializer : BaseDeserializer(Annotation::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Annotation { + val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() + + when (type) { + "file_citation" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Annotation(fileCitation = it, _json = json) + } ?: Annotation(_json = json) + } + "url_citation" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Annotation(urlCitation = it, _json = json) + } ?: Annotation(_json = json) + } + "container_file_citation" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { Annotation(containerFileCitation = it, _json = json) } + ?: Annotation(_json = json) + } + } + + return Annotation(_json = json) + } + } + + internal class Serializer : BaseSerializer(Annotation::class) { + + override fun serialize( + value: Annotation, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.fileCitation != null -> generator.writeObject(value.fileCitation) + value.urlCitation != null -> generator.writeObject(value.urlCitation) + value.containerFileCitation != null -> + generator.writeObject(value.containerFileCitation) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Annotation") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OutputTextContent && + annotations == other.annotations && + text == other.text && + type == other.type && + logprobs == other.logprobs && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(annotations, text, type, logprobs, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "OutputTextContent{annotations=$annotations, text=$text, type=$type, logprobs=$logprobs, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/RefusalContent.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/RefusalContent.kt new file mode 100644 index 000000000..6cc73948e --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/RefusalContent.kt @@ -0,0 +1,213 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +class RefusalContent +private constructor( + private val refusal: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("refusal") @ExcludeMissing refusal: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(refusal, type, mutableMapOf()) + + /** + * The refusal explanation from the model. + * + * @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 refusal(): String = refusal.getRequired("refusal") + + /** + * The type of the refusal. Always `refusal`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("refusal") + * ``` + * + * 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 + + /** + * Returns the raw JSON value of [refusal]. + * + * Unlike [refusal], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("refusal") @ExcludeMissing fun _refusal(): JsonField = refusal + + @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 [RefusalContent]. + * + * The following fields are required: + * ```java + * .refusal() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [RefusalContent]. */ + class Builder internal constructor() { + + private var refusal: JsonField? = null + private var type: JsonValue = JsonValue.from("refusal") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(refusalContent: RefusalContent) = apply { + refusal = refusalContent.refusal + type = refusalContent.type + additionalProperties = refusalContent.additionalProperties.toMutableMap() + } + + /** The refusal explanation from the model. */ + fun refusal(refusal: String) = refusal(JsonField.of(refusal)) + + /** + * Sets [Builder.refusal] to an arbitrary JSON value. + * + * You should usually call [Builder.refusal] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun refusal(refusal: JsonField) = apply { this.refusal = refusal } + + /** + * 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("refusal") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [RefusalContent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .refusal() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): RefusalContent = + RefusalContent( + checkRequired("refusal", refusal), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): RefusalContent = apply { + if (validated) { + return@apply + } + + refusal() + _type().let { + if (it != JsonValue.from("refusal")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 (refusal.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("refusal")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is RefusalContent && + refusal == other.refusal && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(refusal, type, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "RefusalContent{refusal=$refusal, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/SummaryTextContent.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/SummaryTextContent.kt new file mode 100644 index 000000000..263a247c3 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/SummaryTextContent.kt @@ -0,0 +1,208 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +class SummaryTextContent +private constructor( + private val text: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("text") @ExcludeMissing text: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(text, type, mutableMapOf()) + + /** + * @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 text(): String = text.getRequired("text") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("summary_text") + * ``` + * + * 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 + + /** + * 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 + + @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 [SummaryTextContent]. + * + * The following fields are required: + * ```java + * .text() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SummaryTextContent]. */ + class Builder internal constructor() { + + private var text: JsonField? = null + private var type: JsonValue = JsonValue.from("summary_text") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(summaryTextContent: SummaryTextContent) = apply { + text = summaryTextContent.text + type = summaryTextContent.type + additionalProperties = summaryTextContent.additionalProperties.toMutableMap() + } + + fun text(text: String) = text(JsonField.of(text)) + + /** + * Sets [Builder.text] to an arbitrary JSON value. + * + * You should usually call [Builder.text] with a well-typed [String] 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 } + + /** + * 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("summary_text") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [SummaryTextContent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .text() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): SummaryTextContent = + SummaryTextContent( + checkRequired("text", text), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): SummaryTextContent = apply { + if (validated) { + return@apply + } + + text() + _type().let { + if (it != JsonValue.from("summary_text")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 (text.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("summary_text")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SummaryTextContent && + text == other.text && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(text, type, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "SummaryTextContent{text=$text, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/TextContent.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/TextContent.kt new file mode 100644 index 000000000..120f1488b --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/TextContent.kt @@ -0,0 +1,204 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +class TextContent +private constructor( + private val text: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("text") @ExcludeMissing text: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(text, type, mutableMapOf()) + + /** + * @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 text(): String = text.getRequired("text") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("text") + * ``` + * + * 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 + + /** + * 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 + + @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 [TextContent]. + * + * The following fields are required: + * ```java + * .text() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TextContent]. */ + class Builder internal constructor() { + + private var text: JsonField? = null + private var type: JsonValue = JsonValue.from("text") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(textContent: TextContent) = apply { + text = textContent.text + type = textContent.type + additionalProperties = textContent.additionalProperties.toMutableMap() + } + + fun text(text: String) = text(JsonField.of(text)) + + /** + * Sets [Builder.text] to an arbitrary JSON value. + * + * You should usually call [Builder.text] with a well-typed [String] 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 } + + /** + * 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("text") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [TextContent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .text() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TextContent = + TextContent(checkRequired("text", text), type, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): TextContent = apply { + if (validated) { + return@apply + } + + text() + _type().let { + if (it != JsonValue.from("text")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 (text.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("text")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TextContent && + text == other.text && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(text, type, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "TextContent{text=$text, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/TopLogProb.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/TopLogProb.kt new file mode 100644 index 000000000..c9750659f --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/TopLogProb.kt @@ -0,0 +1,253 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkKnown +import com.openai.core.checkRequired +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +class TopLogProb +private constructor( + private val token: JsonField, + private val bytes: JsonField>, + private val logprob: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("token") @ExcludeMissing token: JsonField = JsonMissing.of(), + @JsonProperty("bytes") @ExcludeMissing bytes: JsonField> = JsonMissing.of(), + @JsonProperty("logprob") @ExcludeMissing logprob: JsonField = JsonMissing.of(), + ) : this(token, bytes, logprob, mutableMapOf()) + + /** + * @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 token(): String = token.getRequired("token") + + /** + * @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 bytes(): List = bytes.getRequired("bytes") + + /** + * @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 logprob(): Double = logprob.getRequired("logprob") + + /** + * Returns the raw JSON value of [token]. + * + * Unlike [token], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("token") @ExcludeMissing fun _token(): JsonField = token + + /** + * Returns the raw JSON value of [bytes]. + * + * Unlike [bytes], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("bytes") @ExcludeMissing fun _bytes(): JsonField> = bytes + + /** + * Returns the raw JSON value of [logprob]. + * + * Unlike [logprob], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("logprob") @ExcludeMissing fun _logprob(): JsonField = logprob + + @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 [TopLogProb]. + * + * The following fields are required: + * ```java + * .token() + * .bytes() + * .logprob() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TopLogProb]. */ + class Builder internal constructor() { + + private var token: JsonField? = null + private var bytes: JsonField>? = null + private var logprob: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(topLogProb: TopLogProb) = apply { + token = topLogProb.token + bytes = topLogProb.bytes.map { it.toMutableList() } + logprob = topLogProb.logprob + additionalProperties = topLogProb.additionalProperties.toMutableMap() + } + + fun token(token: String) = token(JsonField.of(token)) + + /** + * Sets [Builder.token] to an arbitrary JSON value. + * + * You should usually call [Builder.token] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun token(token: JsonField) = apply { this.token = token } + + fun bytes(bytes: List) = bytes(JsonField.of(bytes)) + + /** + * Sets [Builder.bytes] to an arbitrary JSON value. + * + * You should usually call [Builder.bytes] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun bytes(bytes: JsonField>) = apply { + this.bytes = bytes.map { it.toMutableList() } + } + + /** + * Adds a single [Long] to [bytes]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addByte(byte_: Long) = apply { + bytes = + (bytes ?: JsonField.of(mutableListOf())).also { checkKnown("bytes", it).add(byte_) } + } + + fun logprob(logprob: Double) = logprob(JsonField.of(logprob)) + + /** + * Sets [Builder.logprob] to an arbitrary JSON value. + * + * You should usually call [Builder.logprob] with a well-typed [Double] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun logprob(logprob: JsonField) = apply { this.logprob = logprob } + + 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 [TopLogProb]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .token() + * .bytes() + * .logprob() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TopLogProb = + TopLogProb( + checkRequired("token", token), + checkRequired("bytes", bytes).map { it.toImmutable() }, + checkRequired("logprob", logprob), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): TopLogProb = apply { + if (validated) { + return@apply + } + + token() + bytes() + logprob() + 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 (token.asKnown().isPresent) 1 else 0) + + (bytes.asKnown().getOrNull()?.size ?: 0) + + (if (logprob.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TopLogProb && + token == other.token && + bytes == other.bytes && + logprob == other.logprob && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(token, bytes, logprob, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "TopLogProb{token=$token, bytes=$bytes, logprob=$logprob, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/UrlCitationBody.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/UrlCitationBody.kt new file mode 100644 index 000000000..fec9209ae --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/UrlCitationBody.kt @@ -0,0 +1,323 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +class UrlCitationBody +private constructor( + private val endIndex: JsonField, + private val startIndex: JsonField, + private val title: JsonField, + private val type: JsonValue, + private val url: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("end_index") @ExcludeMissing endIndex: JsonField = JsonMissing.of(), + @JsonProperty("start_index") @ExcludeMissing startIndex: JsonField = JsonMissing.of(), + @JsonProperty("title") @ExcludeMissing title: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(), + ) : this(endIndex, startIndex, title, type, url, mutableMapOf()) + + /** + * The index of the last character of the URL citation in the message. + * + * @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 endIndex(): Long = endIndex.getRequired("end_index") + + /** + * The index of the first character of the URL citation in the message. + * + * @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 startIndex(): Long = startIndex.getRequired("start_index") + + /** + * The title of the web resource. + * + * @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 title(): String = title.getRequired("title") + + /** + * The type of the URL citation. Always `url_citation`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("url_citation") + * ``` + * + * 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 + + /** + * The URL of the web resource. + * + * @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 url(): String = url.getRequired("url") + + /** + * Returns the raw JSON value of [endIndex]. + * + * Unlike [endIndex], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("end_index") @ExcludeMissing fun _endIndex(): JsonField = endIndex + + /** + * Returns the raw JSON value of [startIndex]. + * + * Unlike [startIndex], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("start_index") @ExcludeMissing fun _startIndex(): JsonField = startIndex + + /** + * Returns the raw JSON value of [title]. + * + * Unlike [title], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("title") @ExcludeMissing fun _title(): JsonField = title + + /** + * Returns the raw JSON value of [url]. + * + * Unlike [url], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("url") @ExcludeMissing fun _url(): JsonField = url + + @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 [UrlCitationBody]. + * + * The following fields are required: + * ```java + * .endIndex() + * .startIndex() + * .title() + * .url() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [UrlCitationBody]. */ + class Builder internal constructor() { + + private var endIndex: JsonField? = null + private var startIndex: JsonField? = null + private var title: JsonField? = null + private var type: JsonValue = JsonValue.from("url_citation") + private var url: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(urlCitationBody: UrlCitationBody) = apply { + endIndex = urlCitationBody.endIndex + startIndex = urlCitationBody.startIndex + title = urlCitationBody.title + type = urlCitationBody.type + url = urlCitationBody.url + additionalProperties = urlCitationBody.additionalProperties.toMutableMap() + } + + /** The index of the last character of the URL citation in the message. */ + fun endIndex(endIndex: Long) = endIndex(JsonField.of(endIndex)) + + /** + * Sets [Builder.endIndex] to an arbitrary JSON value. + * + * You should usually call [Builder.endIndex] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun endIndex(endIndex: JsonField) = apply { this.endIndex = endIndex } + + /** The index of the first character of the URL citation in the message. */ + fun startIndex(startIndex: Long) = startIndex(JsonField.of(startIndex)) + + /** + * Sets [Builder.startIndex] to an arbitrary JSON value. + * + * You should usually call [Builder.startIndex] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun startIndex(startIndex: JsonField) = apply { this.startIndex = startIndex } + + /** The title of the web resource. */ + fun title(title: String) = title(JsonField.of(title)) + + /** + * Sets [Builder.title] to an arbitrary JSON value. + * + * You should usually call [Builder.title] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun title(title: JsonField) = apply { this.title = title } + + /** + * 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("url_citation") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** The URL of the web resource. */ + fun url(url: String) = url(JsonField.of(url)) + + /** + * Sets [Builder.url] to an arbitrary JSON value. + * + * You should usually call [Builder.url] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun url(url: JsonField) = apply { this.url = url } + + 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 [UrlCitationBody]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .endIndex() + * .startIndex() + * .title() + * .url() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): UrlCitationBody = + UrlCitationBody( + checkRequired("endIndex", endIndex), + checkRequired("startIndex", startIndex), + checkRequired("title", title), + type, + checkRequired("url", url), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): UrlCitationBody = apply { + if (validated) { + return@apply + } + + endIndex() + startIndex() + title() + _type().let { + if (it != JsonValue.from("url_citation")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + url() + 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 (endIndex.asKnown().isPresent) 1 else 0) + + (if (startIndex.asKnown().isPresent) 1 else 0) + + (if (title.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("url_citation")) 1 else 0 } + + (if (url.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UrlCitationBody && + endIndex == other.endIndex && + startIndex == other.startIndex && + title == other.title && + type == other.type && + url == other.url && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(endIndex, startIndex, title, type, url, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "UrlCitationBody{endIndex=$endIndex, startIndex=$startIndex, title=$title, type=$type, url=$url, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ConversationItem.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ConversationItem.kt new file mode 100644 index 000000000..c8bd0517d --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ConversationItem.kt @@ -0,0 +1,4309 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +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.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.conversations.Message +import com.openai.models.responses.ResponseCodeInterpreterToolCall +import com.openai.models.responses.ResponseComputerToolCall +import com.openai.models.responses.ResponseComputerToolCallOutputItem +import com.openai.models.responses.ResponseCustomToolCall +import com.openai.models.responses.ResponseCustomToolCallOutput +import com.openai.models.responses.ResponseFileSearchToolCall +import com.openai.models.responses.ResponseFunctionToolCallItem +import com.openai.models.responses.ResponseFunctionToolCallOutputItem +import com.openai.models.responses.ResponseFunctionWebSearch +import com.openai.models.responses.ResponseReasoningItem +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * A single item within a conversation. The set of possible types are the same as the `output` type + * of a + * [Response object](https://platform.openai.com/docs/api-reference/responses/object#responses/object-output). + */ +@JsonDeserialize(using = ConversationItem.Deserializer::class) +@JsonSerialize(using = ConversationItem.Serializer::class) +class ConversationItem +private constructor( + private val message: Message? = null, + private val functionCall: ResponseFunctionToolCallItem? = null, + private val functionCallOutput: ResponseFunctionToolCallOutputItem? = null, + private val fileSearchCall: ResponseFileSearchToolCall? = null, + private val webSearchCall: ResponseFunctionWebSearch? = null, + private val imageGenerationCall: ImageGenerationCall? = null, + private val computerCall: ResponseComputerToolCall? = null, + private val computerCallOutput: ResponseComputerToolCallOutputItem? = null, + private val reasoning: ResponseReasoningItem? = null, + private val codeInterpreterCall: ResponseCodeInterpreterToolCall? = null, + private val localShellCall: LocalShellCall? = null, + private val localShellCallOutput: LocalShellCallOutput? = null, + private val mcpListTools: McpListTools? = null, + private val mcpApprovalRequest: McpApprovalRequest? = null, + private val mcpApprovalResponse: McpApprovalResponse? = null, + private val mcpCall: McpCall? = null, + private val customToolCall: ResponseCustomToolCall? = null, + private val customToolCallOutput: ResponseCustomToolCallOutput? = null, + private val _json: JsonValue? = null, +) { + + fun message(): Optional = Optional.ofNullable(message) + + /** + * A tool call to run a function. See the + * [function calling guide](https://platform.openai.com/docs/guides/function-calling) for more + * information. + */ + fun functionCall(): Optional = Optional.ofNullable(functionCall) + + fun functionCallOutput(): Optional = + Optional.ofNullable(functionCallOutput) + + /** + * The results of a file search tool call. See the + * [file search guide](https://platform.openai.com/docs/guides/tools-file-search) for more + * information. + */ + fun fileSearchCall(): Optional = Optional.ofNullable(fileSearchCall) + + /** + * The results of a web search tool call. See the + * [web search guide](https://platform.openai.com/docs/guides/tools-web-search) for more + * information. + */ + fun webSearchCall(): Optional = Optional.ofNullable(webSearchCall) + + /** An image generation request made by the model. */ + fun imageGenerationCall(): Optional = + Optional.ofNullable(imageGenerationCall) + + /** + * A tool call to a computer use tool. See the + * [computer use guide](https://platform.openai.com/docs/guides/tools-computer-use) for more + * information. + */ + fun computerCall(): Optional = Optional.ofNullable(computerCall) + + fun computerCallOutput(): Optional = + Optional.ofNullable(computerCallOutput) + + /** + * A description of the chain of thought used by a reasoning model while generating a response. + * Be sure to include these items in your `input` to the Responses API for subsequent turns of a + * conversation if you are manually + * [managing context](https://platform.openai.com/docs/guides/conversation-state). + */ + fun reasoning(): Optional = Optional.ofNullable(reasoning) + + /** A tool call to run code. */ + fun codeInterpreterCall(): Optional = + Optional.ofNullable(codeInterpreterCall) + + /** A tool call to run a command on the local shell. */ + fun localShellCall(): Optional = Optional.ofNullable(localShellCall) + + /** The output of a local shell tool call. */ + fun localShellCallOutput(): Optional = + Optional.ofNullable(localShellCallOutput) + + /** A list of tools available on an MCP server. */ + fun mcpListTools(): Optional = Optional.ofNullable(mcpListTools) + + /** A request for human approval of a tool invocation. */ + fun mcpApprovalRequest(): Optional = Optional.ofNullable(mcpApprovalRequest) + + /** A response to an MCP approval request. */ + fun mcpApprovalResponse(): Optional = + Optional.ofNullable(mcpApprovalResponse) + + /** An invocation of a tool on an MCP server. */ + fun mcpCall(): Optional = Optional.ofNullable(mcpCall) + + /** A call to a custom tool created by the model. */ + fun customToolCall(): Optional = Optional.ofNullable(customToolCall) + + /** The output of a custom tool call from your code, being sent back to the model. */ + fun customToolCallOutput(): Optional = + Optional.ofNullable(customToolCallOutput) + + fun isMessage(): Boolean = message != null + + fun isFunctionCall(): Boolean = functionCall != null + + fun isFunctionCallOutput(): Boolean = functionCallOutput != null + + fun isFileSearchCall(): Boolean = fileSearchCall != null + + fun isWebSearchCall(): Boolean = webSearchCall != null + + fun isImageGenerationCall(): Boolean = imageGenerationCall != null + + fun isComputerCall(): Boolean = computerCall != null + + fun isComputerCallOutput(): Boolean = computerCallOutput != null + + fun isReasoning(): Boolean = reasoning != null + + fun isCodeInterpreterCall(): Boolean = codeInterpreterCall != null + + fun isLocalShellCall(): Boolean = localShellCall != null + + fun isLocalShellCallOutput(): Boolean = localShellCallOutput != null + + fun isMcpListTools(): Boolean = mcpListTools != null + + fun isMcpApprovalRequest(): Boolean = mcpApprovalRequest != null + + fun isMcpApprovalResponse(): Boolean = mcpApprovalResponse != null + + fun isMcpCall(): Boolean = mcpCall != null + + fun isCustomToolCall(): Boolean = customToolCall != null + + fun isCustomToolCallOutput(): Boolean = customToolCallOutput != null + + fun asMessage(): Message = message.getOrThrow("message") + + /** + * A tool call to run a function. See the + * [function calling guide](https://platform.openai.com/docs/guides/function-calling) for more + * information. + */ + fun asFunctionCall(): ResponseFunctionToolCallItem = functionCall.getOrThrow("functionCall") + + fun asFunctionCallOutput(): ResponseFunctionToolCallOutputItem = + functionCallOutput.getOrThrow("functionCallOutput") + + /** + * The results of a file search tool call. See the + * [file search guide](https://platform.openai.com/docs/guides/tools-file-search) for more + * information. + */ + fun asFileSearchCall(): ResponseFileSearchToolCall = fileSearchCall.getOrThrow("fileSearchCall") + + /** + * The results of a web search tool call. See the + * [web search guide](https://platform.openai.com/docs/guides/tools-web-search) for more + * information. + */ + fun asWebSearchCall(): ResponseFunctionWebSearch = webSearchCall.getOrThrow("webSearchCall") + + /** An image generation request made by the model. */ + fun asImageGenerationCall(): ImageGenerationCall = + imageGenerationCall.getOrThrow("imageGenerationCall") + + /** + * A tool call to a computer use tool. See the + * [computer use guide](https://platform.openai.com/docs/guides/tools-computer-use) for more + * information. + */ + fun asComputerCall(): ResponseComputerToolCall = computerCall.getOrThrow("computerCall") + + fun asComputerCallOutput(): ResponseComputerToolCallOutputItem = + computerCallOutput.getOrThrow("computerCallOutput") + + /** + * A description of the chain of thought used by a reasoning model while generating a response. + * Be sure to include these items in your `input` to the Responses API for subsequent turns of a + * conversation if you are manually + * [managing context](https://platform.openai.com/docs/guides/conversation-state). + */ + fun asReasoning(): ResponseReasoningItem = reasoning.getOrThrow("reasoning") + + /** A tool call to run code. */ + fun asCodeInterpreterCall(): ResponseCodeInterpreterToolCall = + codeInterpreterCall.getOrThrow("codeInterpreterCall") + + /** A tool call to run a command on the local shell. */ + fun asLocalShellCall(): LocalShellCall = localShellCall.getOrThrow("localShellCall") + + /** The output of a local shell tool call. */ + fun asLocalShellCallOutput(): LocalShellCallOutput = + localShellCallOutput.getOrThrow("localShellCallOutput") + + /** A list of tools available on an MCP server. */ + fun asMcpListTools(): McpListTools = mcpListTools.getOrThrow("mcpListTools") + + /** A request for human approval of a tool invocation. */ + fun asMcpApprovalRequest(): McpApprovalRequest = + mcpApprovalRequest.getOrThrow("mcpApprovalRequest") + + /** A response to an MCP approval request. */ + fun asMcpApprovalResponse(): McpApprovalResponse = + mcpApprovalResponse.getOrThrow("mcpApprovalResponse") + + /** An invocation of a tool on an MCP server. */ + fun asMcpCall(): McpCall = mcpCall.getOrThrow("mcpCall") + + /** A call to a custom tool created by the model. */ + fun asCustomToolCall(): ResponseCustomToolCall = customToolCall.getOrThrow("customToolCall") + + /** The output of a custom tool call from your code, being sent back to the model. */ + fun asCustomToolCallOutput(): ResponseCustomToolCallOutput = + customToolCallOutput.getOrThrow("customToolCallOutput") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + message != null -> visitor.visitMessage(message) + functionCall != null -> visitor.visitFunctionCall(functionCall) + functionCallOutput != null -> visitor.visitFunctionCallOutput(functionCallOutput) + fileSearchCall != null -> visitor.visitFileSearchCall(fileSearchCall) + webSearchCall != null -> visitor.visitWebSearchCall(webSearchCall) + imageGenerationCall != null -> visitor.visitImageGenerationCall(imageGenerationCall) + computerCall != null -> visitor.visitComputerCall(computerCall) + computerCallOutput != null -> visitor.visitComputerCallOutput(computerCallOutput) + reasoning != null -> visitor.visitReasoning(reasoning) + codeInterpreterCall != null -> visitor.visitCodeInterpreterCall(codeInterpreterCall) + localShellCall != null -> visitor.visitLocalShellCall(localShellCall) + localShellCallOutput != null -> visitor.visitLocalShellCallOutput(localShellCallOutput) + mcpListTools != null -> visitor.visitMcpListTools(mcpListTools) + mcpApprovalRequest != null -> visitor.visitMcpApprovalRequest(mcpApprovalRequest) + mcpApprovalResponse != null -> visitor.visitMcpApprovalResponse(mcpApprovalResponse) + mcpCall != null -> visitor.visitMcpCall(mcpCall) + customToolCall != null -> visitor.visitCustomToolCall(customToolCall) + customToolCallOutput != null -> visitor.visitCustomToolCallOutput(customToolCallOutput) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): ConversationItem = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitMessage(message: Message) { + message.validate() + } + + override fun visitFunctionCall(functionCall: ResponseFunctionToolCallItem) { + functionCall.validate() + } + + override fun visitFunctionCallOutput( + functionCallOutput: ResponseFunctionToolCallOutputItem + ) { + functionCallOutput.validate() + } + + override fun visitFileSearchCall(fileSearchCall: ResponseFileSearchToolCall) { + fileSearchCall.validate() + } + + override fun visitWebSearchCall(webSearchCall: ResponseFunctionWebSearch) { + webSearchCall.validate() + } + + override fun visitImageGenerationCall(imageGenerationCall: ImageGenerationCall) { + imageGenerationCall.validate() + } + + override fun visitComputerCall(computerCall: ResponseComputerToolCall) { + computerCall.validate() + } + + override fun visitComputerCallOutput( + computerCallOutput: ResponseComputerToolCallOutputItem + ) { + computerCallOutput.validate() + } + + override fun visitReasoning(reasoning: ResponseReasoningItem) { + reasoning.validate() + } + + override fun visitCodeInterpreterCall( + codeInterpreterCall: ResponseCodeInterpreterToolCall + ) { + codeInterpreterCall.validate() + } + + override fun visitLocalShellCall(localShellCall: LocalShellCall) { + localShellCall.validate() + } + + override fun visitLocalShellCallOutput(localShellCallOutput: LocalShellCallOutput) { + localShellCallOutput.validate() + } + + override fun visitMcpListTools(mcpListTools: McpListTools) { + mcpListTools.validate() + } + + override fun visitMcpApprovalRequest(mcpApprovalRequest: McpApprovalRequest) { + mcpApprovalRequest.validate() + } + + override fun visitMcpApprovalResponse(mcpApprovalResponse: McpApprovalResponse) { + mcpApprovalResponse.validate() + } + + override fun visitMcpCall(mcpCall: McpCall) { + mcpCall.validate() + } + + override fun visitCustomToolCall(customToolCall: ResponseCustomToolCall) { + customToolCall.validate() + } + + override fun visitCustomToolCallOutput( + customToolCallOutput: ResponseCustomToolCallOutput + ) { + customToolCallOutput.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 visitMessage(message: Message) = message.validity() + + override fun visitFunctionCall(functionCall: ResponseFunctionToolCallItem) = + functionCall.validity() + + override fun visitFunctionCallOutput( + functionCallOutput: ResponseFunctionToolCallOutputItem + ) = functionCallOutput.validity() + + override fun visitFileSearchCall(fileSearchCall: ResponseFileSearchToolCall) = + fileSearchCall.validity() + + override fun visitWebSearchCall(webSearchCall: ResponseFunctionWebSearch) = + webSearchCall.validity() + + override fun visitImageGenerationCall(imageGenerationCall: ImageGenerationCall) = + imageGenerationCall.validity() + + override fun visitComputerCall(computerCall: ResponseComputerToolCall) = + computerCall.validity() + + override fun visitComputerCallOutput( + computerCallOutput: ResponseComputerToolCallOutputItem + ) = computerCallOutput.validity() + + override fun visitReasoning(reasoning: ResponseReasoningItem) = reasoning.validity() + + override fun visitCodeInterpreterCall( + codeInterpreterCall: ResponseCodeInterpreterToolCall + ) = codeInterpreterCall.validity() + + override fun visitLocalShellCall(localShellCall: LocalShellCall) = + localShellCall.validity() + + override fun visitLocalShellCallOutput(localShellCallOutput: LocalShellCallOutput) = + localShellCallOutput.validity() + + override fun visitMcpListTools(mcpListTools: McpListTools) = mcpListTools.validity() + + override fun visitMcpApprovalRequest(mcpApprovalRequest: McpApprovalRequest) = + mcpApprovalRequest.validity() + + override fun visitMcpApprovalResponse(mcpApprovalResponse: McpApprovalResponse) = + mcpApprovalResponse.validity() + + override fun visitMcpCall(mcpCall: McpCall) = mcpCall.validity() + + override fun visitCustomToolCall(customToolCall: ResponseCustomToolCall) = + customToolCall.validity() + + override fun visitCustomToolCallOutput( + customToolCallOutput: ResponseCustomToolCallOutput + ) = customToolCallOutput.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConversationItem && + message == other.message && + functionCall == other.functionCall && + functionCallOutput == other.functionCallOutput && + fileSearchCall == other.fileSearchCall && + webSearchCall == other.webSearchCall && + imageGenerationCall == other.imageGenerationCall && + computerCall == other.computerCall && + computerCallOutput == other.computerCallOutput && + reasoning == other.reasoning && + codeInterpreterCall == other.codeInterpreterCall && + localShellCall == other.localShellCall && + localShellCallOutput == other.localShellCallOutput && + mcpListTools == other.mcpListTools && + mcpApprovalRequest == other.mcpApprovalRequest && + mcpApprovalResponse == other.mcpApprovalResponse && + mcpCall == other.mcpCall && + customToolCall == other.customToolCall && + customToolCallOutput == other.customToolCallOutput + } + + override fun hashCode(): Int = + Objects.hash( + message, + functionCall, + functionCallOutput, + fileSearchCall, + webSearchCall, + imageGenerationCall, + computerCall, + computerCallOutput, + reasoning, + codeInterpreterCall, + localShellCall, + localShellCallOutput, + mcpListTools, + mcpApprovalRequest, + mcpApprovalResponse, + mcpCall, + customToolCall, + customToolCallOutput, + ) + + override fun toString(): String = + when { + message != null -> "ConversationItem{message=$message}" + functionCall != null -> "ConversationItem{functionCall=$functionCall}" + functionCallOutput != null -> "ConversationItem{functionCallOutput=$functionCallOutput}" + fileSearchCall != null -> "ConversationItem{fileSearchCall=$fileSearchCall}" + webSearchCall != null -> "ConversationItem{webSearchCall=$webSearchCall}" + imageGenerationCall != null -> + "ConversationItem{imageGenerationCall=$imageGenerationCall}" + computerCall != null -> "ConversationItem{computerCall=$computerCall}" + computerCallOutput != null -> "ConversationItem{computerCallOutput=$computerCallOutput}" + reasoning != null -> "ConversationItem{reasoning=$reasoning}" + codeInterpreterCall != null -> + "ConversationItem{codeInterpreterCall=$codeInterpreterCall}" + localShellCall != null -> "ConversationItem{localShellCall=$localShellCall}" + localShellCallOutput != null -> + "ConversationItem{localShellCallOutput=$localShellCallOutput}" + mcpListTools != null -> "ConversationItem{mcpListTools=$mcpListTools}" + mcpApprovalRequest != null -> "ConversationItem{mcpApprovalRequest=$mcpApprovalRequest}" + mcpApprovalResponse != null -> + "ConversationItem{mcpApprovalResponse=$mcpApprovalResponse}" + mcpCall != null -> "ConversationItem{mcpCall=$mcpCall}" + customToolCall != null -> "ConversationItem{customToolCall=$customToolCall}" + customToolCallOutput != null -> + "ConversationItem{customToolCallOutput=$customToolCallOutput}" + _json != null -> "ConversationItem{_unknown=$_json}" + else -> throw IllegalStateException("Invalid ConversationItem") + } + + companion object { + + @JvmStatic fun ofMessage(message: Message) = ConversationItem(message = message) + + /** + * A tool call to run a function. See the + * [function calling guide](https://platform.openai.com/docs/guides/function-calling) for + * more information. + */ + @JvmStatic + fun ofFunctionCall(functionCall: ResponseFunctionToolCallItem) = + ConversationItem(functionCall = functionCall) + + @JvmStatic + fun ofFunctionCallOutput(functionCallOutput: ResponseFunctionToolCallOutputItem) = + ConversationItem(functionCallOutput = functionCallOutput) + + /** + * The results of a file search tool call. See the + * [file search guide](https://platform.openai.com/docs/guides/tools-file-search) for more + * information. + */ + @JvmStatic + fun ofFileSearchCall(fileSearchCall: ResponseFileSearchToolCall) = + ConversationItem(fileSearchCall = fileSearchCall) + + /** + * The results of a web search tool call. See the + * [web search guide](https://platform.openai.com/docs/guides/tools-web-search) for more + * information. + */ + @JvmStatic + fun ofWebSearchCall(webSearchCall: ResponseFunctionWebSearch) = + ConversationItem(webSearchCall = webSearchCall) + + /** An image generation request made by the model. */ + @JvmStatic + fun ofImageGenerationCall(imageGenerationCall: ImageGenerationCall) = + ConversationItem(imageGenerationCall = imageGenerationCall) + + /** + * A tool call to a computer use tool. See the + * [computer use guide](https://platform.openai.com/docs/guides/tools-computer-use) for more + * information. + */ + @JvmStatic + fun ofComputerCall(computerCall: ResponseComputerToolCall) = + ConversationItem(computerCall = computerCall) + + @JvmStatic + fun ofComputerCallOutput(computerCallOutput: ResponseComputerToolCallOutputItem) = + ConversationItem(computerCallOutput = computerCallOutput) + + /** + * A description of the chain of thought used by a reasoning model while generating a + * response. Be sure to include these items in your `input` to the Responses API for + * subsequent turns of a conversation if you are manually + * [managing context](https://platform.openai.com/docs/guides/conversation-state). + */ + @JvmStatic + fun ofReasoning(reasoning: ResponseReasoningItem) = ConversationItem(reasoning = reasoning) + + /** A tool call to run code. */ + @JvmStatic + fun ofCodeInterpreterCall(codeInterpreterCall: ResponseCodeInterpreterToolCall) = + ConversationItem(codeInterpreterCall = codeInterpreterCall) + + /** A tool call to run a command on the local shell. */ + @JvmStatic + fun ofLocalShellCall(localShellCall: LocalShellCall) = + ConversationItem(localShellCall = localShellCall) + + /** The output of a local shell tool call. */ + @JvmStatic + fun ofLocalShellCallOutput(localShellCallOutput: LocalShellCallOutput) = + ConversationItem(localShellCallOutput = localShellCallOutput) + + /** A list of tools available on an MCP server. */ + @JvmStatic + fun ofMcpListTools(mcpListTools: McpListTools) = + ConversationItem(mcpListTools = mcpListTools) + + /** A request for human approval of a tool invocation. */ + @JvmStatic + fun ofMcpApprovalRequest(mcpApprovalRequest: McpApprovalRequest) = + ConversationItem(mcpApprovalRequest = mcpApprovalRequest) + + /** A response to an MCP approval request. */ + @JvmStatic + fun ofMcpApprovalResponse(mcpApprovalResponse: McpApprovalResponse) = + ConversationItem(mcpApprovalResponse = mcpApprovalResponse) + + /** An invocation of a tool on an MCP server. */ + @JvmStatic fun ofMcpCall(mcpCall: McpCall) = ConversationItem(mcpCall = mcpCall) + + /** A call to a custom tool created by the model. */ + @JvmStatic + fun ofCustomToolCall(customToolCall: ResponseCustomToolCall) = + ConversationItem(customToolCall = customToolCall) + + /** The output of a custom tool call from your code, being sent back to the model. */ + @JvmStatic + fun ofCustomToolCallOutput(customToolCallOutput: ResponseCustomToolCallOutput) = + ConversationItem(customToolCallOutput = customToolCallOutput) + } + + /** + * An interface that defines how to map each variant of [ConversationItem] to a value of type + * [T]. + */ + interface Visitor { + + fun visitMessage(message: Message): T + + /** + * A tool call to run a function. See the + * [function calling guide](https://platform.openai.com/docs/guides/function-calling) for + * more information. + */ + fun visitFunctionCall(functionCall: ResponseFunctionToolCallItem): T + + fun visitFunctionCallOutput(functionCallOutput: ResponseFunctionToolCallOutputItem): T + + /** + * The results of a file search tool call. See the + * [file search guide](https://platform.openai.com/docs/guides/tools-file-search) for more + * information. + */ + fun visitFileSearchCall(fileSearchCall: ResponseFileSearchToolCall): T + + /** + * The results of a web search tool call. See the + * [web search guide](https://platform.openai.com/docs/guides/tools-web-search) for more + * information. + */ + fun visitWebSearchCall(webSearchCall: ResponseFunctionWebSearch): T + + /** An image generation request made by the model. */ + fun visitImageGenerationCall(imageGenerationCall: ImageGenerationCall): T + + /** + * A tool call to a computer use tool. See the + * [computer use guide](https://platform.openai.com/docs/guides/tools-computer-use) for more + * information. + */ + fun visitComputerCall(computerCall: ResponseComputerToolCall): T + + fun visitComputerCallOutput(computerCallOutput: ResponseComputerToolCallOutputItem): T + + /** + * A description of the chain of thought used by a reasoning model while generating a + * response. Be sure to include these items in your `input` to the Responses API for + * subsequent turns of a conversation if you are manually + * [managing context](https://platform.openai.com/docs/guides/conversation-state). + */ + fun visitReasoning(reasoning: ResponseReasoningItem): T + + /** A tool call to run code. */ + fun visitCodeInterpreterCall(codeInterpreterCall: ResponseCodeInterpreterToolCall): T + + /** A tool call to run a command on the local shell. */ + fun visitLocalShellCall(localShellCall: LocalShellCall): T + + /** The output of a local shell tool call. */ + fun visitLocalShellCallOutput(localShellCallOutput: LocalShellCallOutput): T + + /** A list of tools available on an MCP server. */ + fun visitMcpListTools(mcpListTools: McpListTools): T + + /** A request for human approval of a tool invocation. */ + fun visitMcpApprovalRequest(mcpApprovalRequest: McpApprovalRequest): T + + /** A response to an MCP approval request. */ + fun visitMcpApprovalResponse(mcpApprovalResponse: McpApprovalResponse): T + + /** An invocation of a tool on an MCP server. */ + fun visitMcpCall(mcpCall: McpCall): T + + /** A call to a custom tool created by the model. */ + fun visitCustomToolCall(customToolCall: ResponseCustomToolCall): T + + /** The output of a custom tool call from your code, being sent back to the model. */ + fun visitCustomToolCallOutput(customToolCallOutput: ResponseCustomToolCallOutput): T + + /** + * Maps an unknown variant of [ConversationItem] to a value of type [T]. + * + * An instance of [ConversationItem] 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 ConversationItem: $json") + } + } + + internal class Deserializer : BaseDeserializer(ConversationItem::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): ConversationItem { + val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() + + when (type) { + "message" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(message = it, _json = json) + } ?: ConversationItem(_json = json) + } + "function_call" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { ConversationItem(functionCall = it, _json = json) } + ?: ConversationItem(_json = json) + } + "function_call_output" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { ConversationItem(functionCallOutput = it, _json = json) } + ?: ConversationItem(_json = json) + } + "file_search_call" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(fileSearchCall = it, _json = json) + } ?: ConversationItem(_json = json) + } + "web_search_call" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(webSearchCall = it, _json = json) + } ?: ConversationItem(_json = json) + } + "image_generation_call" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(imageGenerationCall = it, _json = json) + } ?: ConversationItem(_json = json) + } + "computer_call" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(computerCall = it, _json = json) + } ?: ConversationItem(_json = json) + } + "computer_call_output" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { ConversationItem(computerCallOutput = it, _json = json) } + ?: ConversationItem(_json = json) + } + "reasoning" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(reasoning = it, _json = json) + } ?: ConversationItem(_json = json) + } + "code_interpreter_call" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { ConversationItem(codeInterpreterCall = it, _json = json) } + ?: ConversationItem(_json = json) + } + "local_shell_call" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(localShellCall = it, _json = json) + } ?: ConversationItem(_json = json) + } + "local_shell_call_output" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(localShellCallOutput = it, _json = json) + } ?: ConversationItem(_json = json) + } + "mcp_list_tools" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(mcpListTools = it, _json = json) + } ?: ConversationItem(_json = json) + } + "mcp_approval_request" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(mcpApprovalRequest = it, _json = json) + } ?: ConversationItem(_json = json) + } + "mcp_approval_response" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(mcpApprovalResponse = it, _json = json) + } ?: ConversationItem(_json = json) + } + "mcp_call" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(mcpCall = it, _json = json) + } ?: ConversationItem(_json = json) + } + "custom_tool_call" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + ConversationItem(customToolCall = it, _json = json) + } ?: ConversationItem(_json = json) + } + "custom_tool_call_output" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { ConversationItem(customToolCallOutput = it, _json = json) } + ?: ConversationItem(_json = json) + } + } + + return ConversationItem(_json = json) + } + } + + internal class Serializer : BaseSerializer(ConversationItem::class) { + + override fun serialize( + value: ConversationItem, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.message != null -> generator.writeObject(value.message) + value.functionCall != null -> generator.writeObject(value.functionCall) + value.functionCallOutput != null -> generator.writeObject(value.functionCallOutput) + value.fileSearchCall != null -> generator.writeObject(value.fileSearchCall) + value.webSearchCall != null -> generator.writeObject(value.webSearchCall) + value.imageGenerationCall != null -> + generator.writeObject(value.imageGenerationCall) + value.computerCall != null -> generator.writeObject(value.computerCall) + value.computerCallOutput != null -> generator.writeObject(value.computerCallOutput) + value.reasoning != null -> generator.writeObject(value.reasoning) + value.codeInterpreterCall != null -> + generator.writeObject(value.codeInterpreterCall) + value.localShellCall != null -> generator.writeObject(value.localShellCall) + value.localShellCallOutput != null -> + generator.writeObject(value.localShellCallOutput) + value.mcpListTools != null -> generator.writeObject(value.mcpListTools) + value.mcpApprovalRequest != null -> generator.writeObject(value.mcpApprovalRequest) + value.mcpApprovalResponse != null -> + generator.writeObject(value.mcpApprovalResponse) + value.mcpCall != null -> generator.writeObject(value.mcpCall) + value.customToolCall != null -> generator.writeObject(value.customToolCall) + value.customToolCallOutput != null -> + generator.writeObject(value.customToolCallOutput) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid ConversationItem") + } + } + } + + /** An image generation request made by the model. */ + class ImageGenerationCall + private constructor( + private val id: JsonField, + private val result: JsonField, + private val status: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("result") @ExcludeMissing result: JsonField = JsonMissing.of(), + @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(id, result, status, type, mutableMapOf()) + + /** + * The unique ID of the image generation call. + * + * @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 id(): String = id.getRequired("id") + + /** + * The generated image encoded in base64. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun result(): Optional = result.getOptional("result") + + /** + * The status of the image generation call. + * + * @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 status(): Status = status.getRequired("status") + + /** + * The type of the image generation call. Always `image_generation_call`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("image_generation_call") + * ``` + * + * 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 + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [result]. + * + * Unlike [result], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("result") @ExcludeMissing fun _result(): JsonField = result + + /** + * Returns the raw JSON value of [status]. + * + * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + + @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 [ImageGenerationCall]. + * + * The following fields are required: + * ```java + * .id() + * .result() + * .status() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ImageGenerationCall]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var result: JsonField? = null + private var status: JsonField? = null + private var type: JsonValue = JsonValue.from("image_generation_call") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(imageGenerationCall: ImageGenerationCall) = apply { + id = imageGenerationCall.id + result = imageGenerationCall.result + status = imageGenerationCall.status + type = imageGenerationCall.type + additionalProperties = imageGenerationCall.additionalProperties.toMutableMap() + } + + /** The unique ID of the image generation call. */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** The generated image encoded in base64. */ + fun result(result: String?) = result(JsonField.ofNullable(result)) + + /** Alias for calling [Builder.result] with `result.orElse(null)`. */ + fun result(result: Optional) = result(result.getOrNull()) + + /** + * Sets [Builder.result] to an arbitrary JSON value. + * + * You should usually call [Builder.result] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun result(result: JsonField) = apply { this.result = result } + + /** The status of the image generation call. */ + fun status(status: Status) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [Status] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun status(status: JsonField) = apply { this.status = status } + + /** + * 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("image_generation_call") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [ImageGenerationCall]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .result() + * .status() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ImageGenerationCall = + ImageGenerationCall( + checkRequired("id", id), + checkRequired("result", result), + checkRequired("status", status), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ImageGenerationCall = apply { + if (validated) { + return@apply + } + + id() + result() + status().validate() + _type().let { + if (it != JsonValue.from("image_generation_call")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 (id.asKnown().isPresent) 1 else 0) + + (if (result.asKnown().isPresent) 1 else 0) + + (status.asKnown().getOrNull()?.validity() ?: 0) + + type.let { if (it == JsonValue.from("image_generation_call")) 1 else 0 } + + /** The status of the image generation call. */ + class Status @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_PROGRESS = of("in_progress") + + @JvmField val COMPLETED = of("completed") + + @JvmField val GENERATING = of("generating") + + @JvmField val FAILED = of("failed") + + @JvmStatic fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + IN_PROGRESS, + COMPLETED, + GENERATING, + FAILED, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] 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_PROGRESS, + COMPLETED, + GENERATING, + FAILED, + /** + * An enum member indicating that [Status] 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_PROGRESS -> Value.IN_PROGRESS + COMPLETED -> Value.COMPLETED + GENERATING -> Value.GENERATING + FAILED -> Value.FAILED + 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_PROGRESS -> Known.IN_PROGRESS + COMPLETED -> Known.COMPLETED + GENERATING -> Known.GENERATING + FAILED -> Known.FAILED + else -> throw OpenAIInvalidDataException("Unknown Status: $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(): Status = 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 Status && 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 ImageGenerationCall && + id == other.id && + result == other.result && + status == other.status && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(id, result, status, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ImageGenerationCall{id=$id, result=$result, status=$status, type=$type, additionalProperties=$additionalProperties}" + } + + /** A tool call to run a command on the local shell. */ + class LocalShellCall + private constructor( + private val id: JsonField, + private val action: JsonField, + private val callId: JsonField, + private val status: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("action") @ExcludeMissing action: JsonField = JsonMissing.of(), + @JsonProperty("call_id") @ExcludeMissing callId: JsonField = JsonMissing.of(), + @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(id, action, callId, status, type, mutableMapOf()) + + /** + * The unique ID of the local shell call. + * + * @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 id(): String = id.getRequired("id") + + /** + * Execute a shell command on the server. + * + * @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 action(): Action = action.getRequired("action") + + /** + * The unique ID of the local shell tool call generated by the model. + * + * @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 callId(): String = callId.getRequired("call_id") + + /** + * The status of the local shell call. + * + * @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 status(): Status = status.getRequired("status") + + /** + * The type of the local shell call. Always `local_shell_call`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("local_shell_call") + * ``` + * + * 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 + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [callId]. + * + * Unlike [callId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("call_id") @ExcludeMissing fun _callId(): JsonField = callId + + /** + * Returns the raw JSON value of [status]. + * + * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + + @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 [LocalShellCall]. + * + * The following fields are required: + * ```java + * .id() + * .action() + * .callId() + * .status() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LocalShellCall]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var action: JsonField? = null + private var callId: JsonField? = null + private var status: JsonField? = null + private var type: JsonValue = JsonValue.from("local_shell_call") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(localShellCall: LocalShellCall) = apply { + id = localShellCall.id + action = localShellCall.action + callId = localShellCall.callId + status = localShellCall.status + type = localShellCall.type + additionalProperties = localShellCall.additionalProperties.toMutableMap() + } + + /** The unique ID of the local shell call. */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** Execute a shell command on the server. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + /** The unique ID of the local shell tool call generated by the model. */ + fun callId(callId: String) = callId(JsonField.of(callId)) + + /** + * Sets [Builder.callId] to an arbitrary JSON value. + * + * You should usually call [Builder.callId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun callId(callId: JsonField) = apply { this.callId = callId } + + /** The status of the local shell call. */ + fun status(status: Status) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [Status] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun status(status: JsonField) = apply { this.status = status } + + /** + * 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("local_shell_call") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [LocalShellCall]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .action() + * .callId() + * .status() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): LocalShellCall = + LocalShellCall( + checkRequired("id", id), + checkRequired("action", action), + checkRequired("callId", callId), + checkRequired("status", status), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): LocalShellCall = apply { + if (validated) { + return@apply + } + + id() + action().validate() + callId() + status().validate() + _type().let { + if (it != JsonValue.from("local_shell_call")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 (id.asKnown().isPresent) 1 else 0) + + (action.asKnown().getOrNull()?.validity() ?: 0) + + (if (callId.asKnown().isPresent) 1 else 0) + + (status.asKnown().getOrNull()?.validity() ?: 0) + + type.let { if (it == JsonValue.from("local_shell_call")) 1 else 0 } + + /** Execute a shell command on the server. */ + class Action + private constructor( + private val command: JsonField>, + private val env: JsonField, + private val type: JsonValue, + private val timeoutMs: JsonField, + private val user: JsonField, + private val workingDirectory: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("command") + @ExcludeMissing + command: JsonField> = JsonMissing.of(), + @JsonProperty("env") @ExcludeMissing env: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("timeout_ms") + @ExcludeMissing + timeoutMs: JsonField = JsonMissing.of(), + @JsonProperty("user") @ExcludeMissing user: JsonField = JsonMissing.of(), + @JsonProperty("working_directory") + @ExcludeMissing + workingDirectory: JsonField = JsonMissing.of(), + ) : this(command, env, type, timeoutMs, user, workingDirectory, mutableMapOf()) + + /** + * The command to run. + * + * @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 command(): List = command.getRequired("command") + + /** + * Environment variables to set for the command. + * + * @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 env(): Env = env.getRequired("env") + + /** + * The type of the local shell action. Always `exec`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("exec") + * ``` + * + * 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 + + /** + * Optional timeout in milliseconds for the command. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun timeoutMs(): Optional = timeoutMs.getOptional("timeout_ms") + + /** + * Optional user to run the command as. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun user(): Optional = user.getOptional("user") + + /** + * Optional working directory to run the command in. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun workingDirectory(): Optional = + workingDirectory.getOptional("working_directory") + + /** + * Returns the raw JSON value of [command]. + * + * Unlike [command], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("command") + @ExcludeMissing + fun _command(): JsonField> = command + + /** + * Returns the raw JSON value of [env]. + * + * Unlike [env], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("env") @ExcludeMissing fun _env(): JsonField = env + + /** + * Returns the raw JSON value of [timeoutMs]. + * + * Unlike [timeoutMs], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("timeout_ms") + @ExcludeMissing + fun _timeoutMs(): JsonField = timeoutMs + + /** + * Returns the raw JSON value of [user]. + * + * Unlike [user], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("user") @ExcludeMissing fun _user(): JsonField = user + + /** + * Returns the raw JSON value of [workingDirectory]. + * + * Unlike [workingDirectory], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("working_directory") + @ExcludeMissing + fun _workingDirectory(): JsonField = workingDirectory + + @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 [Action]. + * + * The following fields are required: + * ```java + * .command() + * .env() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Action]. */ + class Builder internal constructor() { + + private var command: JsonField>? = null + private var env: JsonField? = null + private var type: JsonValue = JsonValue.from("exec") + private var timeoutMs: JsonField = JsonMissing.of() + private var user: JsonField = JsonMissing.of() + private var workingDirectory: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(action: Action) = apply { + command = action.command.map { it.toMutableList() } + env = action.env + type = action.type + timeoutMs = action.timeoutMs + user = action.user + workingDirectory = action.workingDirectory + additionalProperties = action.additionalProperties.toMutableMap() + } + + /** The command to run. */ + fun command(command: List) = command(JsonField.of(command)) + + /** + * Sets [Builder.command] to an arbitrary JSON value. + * + * You should usually call [Builder.command] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun command(command: JsonField>) = apply { + this.command = command.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [Builder.command]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCommand(command: String) = apply { + this.command = + (this.command ?: JsonField.of(mutableListOf())).also { + checkKnown("command", it).add(command) + } + } + + /** Environment variables to set for the command. */ + fun env(env: Env) = env(JsonField.of(env)) + + /** + * Sets [Builder.env] to an arbitrary JSON value. + * + * You should usually call [Builder.env] with a well-typed [Env] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun env(env: JsonField) = apply { this.env = env } + + /** + * 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("exec") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** Optional timeout in milliseconds for the command. */ + fun timeoutMs(timeoutMs: Long?) = timeoutMs(JsonField.ofNullable(timeoutMs)) + + /** + * Alias for [Builder.timeoutMs]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun timeoutMs(timeoutMs: Long) = timeoutMs(timeoutMs as Long?) + + /** Alias for calling [Builder.timeoutMs] with `timeoutMs.orElse(null)`. */ + fun timeoutMs(timeoutMs: Optional) = timeoutMs(timeoutMs.getOrNull()) + + /** + * Sets [Builder.timeoutMs] to an arbitrary JSON value. + * + * You should usually call [Builder.timeoutMs] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun timeoutMs(timeoutMs: JsonField) = apply { this.timeoutMs = timeoutMs } + + /** Optional user to run the command as. */ + fun user(user: String?) = user(JsonField.ofNullable(user)) + + /** Alias for calling [Builder.user] with `user.orElse(null)`. */ + fun user(user: Optional) = user(user.getOrNull()) + + /** + * 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. + */ + fun user(user: JsonField) = apply { this.user = user } + + /** Optional working directory to run the command in. */ + fun workingDirectory(workingDirectory: String?) = + workingDirectory(JsonField.ofNullable(workingDirectory)) + + /** + * Alias for calling [Builder.workingDirectory] with + * `workingDirectory.orElse(null)`. + */ + fun workingDirectory(workingDirectory: Optional) = + workingDirectory(workingDirectory.getOrNull()) + + /** + * Sets [Builder.workingDirectory] to an arbitrary JSON value. + * + * You should usually call [Builder.workingDirectory] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun workingDirectory(workingDirectory: JsonField) = apply { + this.workingDirectory = workingDirectory + } + + 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 [Action]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .command() + * .env() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Action = + Action( + checkRequired("command", command).map { it.toImmutable() }, + checkRequired("env", env), + type, + timeoutMs, + user, + workingDirectory, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Action = apply { + if (validated) { + return@apply + } + + command() + env().validate() + _type().let { + if (it != JsonValue.from("exec")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + timeoutMs() + user() + workingDirectory() + 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 = + (command.asKnown().getOrNull()?.size ?: 0) + + (env.asKnown().getOrNull()?.validity() ?: 0) + + type.let { if (it == JsonValue.from("exec")) 1 else 0 } + + (if (timeoutMs.asKnown().isPresent) 1 else 0) + + (if (user.asKnown().isPresent) 1 else 0) + + (if (workingDirectory.asKnown().isPresent) 1 else 0) + + /** Environment variables to set for the command. */ + class Env + @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 [Env]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Env]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(env: Env) = apply { + additionalProperties = env.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 [Env]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Env = Env(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + fun validate(): Env = 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 Env && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Env{additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Action && + command == other.command && + env == other.env && + type == other.type && + timeoutMs == other.timeoutMs && + user == other.user && + workingDirectory == other.workingDirectory && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + command, + env, + type, + timeoutMs, + user, + workingDirectory, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Action{command=$command, env=$env, type=$type, timeoutMs=$timeoutMs, user=$user, workingDirectory=$workingDirectory, additionalProperties=$additionalProperties}" + } + + /** The status of the local shell call. */ + class Status @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_PROGRESS = of("in_progress") + + @JvmField val COMPLETED = of("completed") + + @JvmField val INCOMPLETE = of("incomplete") + + @JvmStatic fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + IN_PROGRESS, + COMPLETED, + INCOMPLETE, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] 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_PROGRESS, + COMPLETED, + INCOMPLETE, + /** + * An enum member indicating that [Status] 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_PROGRESS -> Value.IN_PROGRESS + COMPLETED -> Value.COMPLETED + INCOMPLETE -> Value.INCOMPLETE + 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_PROGRESS -> Known.IN_PROGRESS + COMPLETED -> Known.COMPLETED + INCOMPLETE -> Known.INCOMPLETE + else -> throw OpenAIInvalidDataException("Unknown Status: $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(): Status = 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 Status && 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 LocalShellCall && + id == other.id && + action == other.action && + callId == other.callId && + status == other.status && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(id, action, callId, status, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "LocalShellCall{id=$id, action=$action, callId=$callId, status=$status, type=$type, additionalProperties=$additionalProperties}" + } + + /** The output of a local shell tool call. */ + class LocalShellCallOutput + private constructor( + private val id: JsonField, + private val output: JsonField, + private val type: JsonValue, + private val status: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("output") @ExcludeMissing output: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + ) : this(id, output, type, status, mutableMapOf()) + + /** + * The unique ID of the local shell tool call generated by the model. + * + * @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 id(): String = id.getRequired("id") + + /** + * A JSON string of the output of the local shell tool call. + * + * @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 output(): String = output.getRequired("output") + + /** + * The type of the local shell tool call output. Always `local_shell_call_output`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("local_shell_call_output") + * ``` + * + * 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 + + /** + * The status of the item. One of `in_progress`, `completed`, or `incomplete`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun status(): Optional = status.getOptional("status") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [output]. + * + * Unlike [output], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("output") @ExcludeMissing fun _output(): JsonField = output + + /** + * Returns the raw JSON value of [status]. + * + * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + + @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 [LocalShellCallOutput]. + * + * The following fields are required: + * ```java + * .id() + * .output() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LocalShellCallOutput]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var output: JsonField? = null + private var type: JsonValue = JsonValue.from("local_shell_call_output") + private var status: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(localShellCallOutput: LocalShellCallOutput) = apply { + id = localShellCallOutput.id + output = localShellCallOutput.output + type = localShellCallOutput.type + status = localShellCallOutput.status + additionalProperties = localShellCallOutput.additionalProperties.toMutableMap() + } + + /** The unique ID of the local shell tool call generated by the model. */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** A JSON string of the output of the local shell tool call. */ + fun output(output: String) = output(JsonField.of(output)) + + /** + * Sets [Builder.output] to an arbitrary JSON value. + * + * You should usually call [Builder.output] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun output(output: JsonField) = apply { this.output = output } + + /** + * 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("local_shell_call_output") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** The status of the item. One of `in_progress`, `completed`, or `incomplete`. */ + fun status(status: Status?) = status(JsonField.ofNullable(status)) + + /** Alias for calling [Builder.status] with `status.orElse(null)`. */ + fun status(status: Optional) = status(status.getOrNull()) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [Status] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun status(status: JsonField) = apply { this.status = status } + + 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 [LocalShellCallOutput]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .output() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): LocalShellCallOutput = + LocalShellCallOutput( + checkRequired("id", id), + checkRequired("output", output), + type, + status, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): LocalShellCallOutput = apply { + if (validated) { + return@apply + } + + id() + output() + _type().let { + if (it != JsonValue.from("local_shell_call_output")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + status().ifPresent { 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 = + (if (id.asKnown().isPresent) 1 else 0) + + (if (output.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("local_shell_call_output")) 1 else 0 } + + (status.asKnown().getOrNull()?.validity() ?: 0) + + /** The status of the item. One of `in_progress`, `completed`, or `incomplete`. */ + class Status @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_PROGRESS = of("in_progress") + + @JvmField val COMPLETED = of("completed") + + @JvmField val INCOMPLETE = of("incomplete") + + @JvmStatic fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + IN_PROGRESS, + COMPLETED, + INCOMPLETE, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] 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_PROGRESS, + COMPLETED, + INCOMPLETE, + /** + * An enum member indicating that [Status] 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_PROGRESS -> Value.IN_PROGRESS + COMPLETED -> Value.COMPLETED + INCOMPLETE -> Value.INCOMPLETE + 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_PROGRESS -> Known.IN_PROGRESS + COMPLETED -> Known.COMPLETED + INCOMPLETE -> Known.INCOMPLETE + else -> throw OpenAIInvalidDataException("Unknown Status: $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(): Status = 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 Status && 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 LocalShellCallOutput && + id == other.id && + output == other.output && + type == other.type && + status == other.status && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(id, output, type, status, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "LocalShellCallOutput{id=$id, output=$output, type=$type, status=$status, additionalProperties=$additionalProperties}" + } + + /** A list of tools available on an MCP server. */ + class McpListTools + private constructor( + private val id: JsonField, + private val serverLabel: JsonField, + private val tools: JsonField>, + private val type: JsonValue, + private val error: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("server_label") + @ExcludeMissing + serverLabel: JsonField = JsonMissing.of(), + @JsonProperty("tools") @ExcludeMissing tools: JsonField> = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("error") @ExcludeMissing error: JsonField = JsonMissing.of(), + ) : this(id, serverLabel, tools, type, error, mutableMapOf()) + + /** + * The unique ID of the list. + * + * @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 id(): String = id.getRequired("id") + + /** + * The label of the MCP server. + * + * @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 serverLabel(): String = serverLabel.getRequired("server_label") + + /** + * The tools available on the server. + * + * @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 tools(): List = tools.getRequired("tools") + + /** + * The type of the item. Always `mcp_list_tools`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("mcp_list_tools") + * ``` + * + * 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 + + /** + * Error message if the server could not list tools. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun error(): Optional = error.getOptional("error") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [serverLabel]. + * + * Unlike [serverLabel], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("server_label") + @ExcludeMissing + fun _serverLabel(): JsonField = serverLabel + + /** + * 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 [error]. + * + * Unlike [error], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("error") @ExcludeMissing fun _error(): JsonField = error + + @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 [McpListTools]. + * + * The following fields are required: + * ```java + * .id() + * .serverLabel() + * .tools() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [McpListTools]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var serverLabel: JsonField? = null + private var tools: JsonField>? = null + private var type: JsonValue = JsonValue.from("mcp_list_tools") + private var error: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(mcpListTools: McpListTools) = apply { + id = mcpListTools.id + serverLabel = mcpListTools.serverLabel + tools = mcpListTools.tools.map { it.toMutableList() } + type = mcpListTools.type + error = mcpListTools.error + additionalProperties = mcpListTools.additionalProperties.toMutableMap() + } + + /** The unique ID of the list. */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** The label of the MCP server. */ + fun serverLabel(serverLabel: String) = serverLabel(JsonField.of(serverLabel)) + + /** + * Sets [Builder.serverLabel] to an arbitrary JSON value. + * + * You should usually call [Builder.serverLabel] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun serverLabel(serverLabel: JsonField) = apply { + this.serverLabel = serverLabel + } + + /** The tools available on the server. */ + 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) + } + } + + /** + * 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("mcp_list_tools") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** Error message if the server could not list tools. */ + fun error(error: String?) = error(JsonField.ofNullable(error)) + + /** Alias for calling [Builder.error] with `error.orElse(null)`. */ + fun error(error: Optional) = error(error.getOrNull()) + + /** + * Sets [Builder.error] to an arbitrary JSON value. + * + * You should usually call [Builder.error] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun error(error: JsonField) = apply { this.error = error } + + 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 [McpListTools]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .serverLabel() + * .tools() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): McpListTools = + McpListTools( + checkRequired("id", id), + checkRequired("serverLabel", serverLabel), + checkRequired("tools", tools).map { it.toImmutable() }, + type, + error, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): McpListTools = apply { + if (validated) { + return@apply + } + + id() + serverLabel() + tools().forEach { it.validate() } + _type().let { + if (it != JsonValue.from("mcp_list_tools")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + error() + 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 (id.asKnown().isPresent) 1 else 0) + + (if (serverLabel.asKnown().isPresent) 1 else 0) + + (tools.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + type.let { if (it == JsonValue.from("mcp_list_tools")) 1 else 0 } + + (if (error.asKnown().isPresent) 1 else 0) + + /** A tool available on an MCP server. */ + class Tool + private constructor( + private val inputSchema: JsonValue, + private val name: JsonField, + private val annotations: JsonValue, + private val description: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("input_schema") + @ExcludeMissing + inputSchema: JsonValue = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("annotations") + @ExcludeMissing + annotations: JsonValue = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + ) : this(inputSchema, name, annotations, description, mutableMapOf()) + + /** The JSON schema describing the tool's input. */ + @JsonProperty("input_schema") + @ExcludeMissing + fun _inputSchema(): JsonValue = inputSchema + + /** + * The name of the tool. + * + * @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 name(): String = name.getRequired("name") + + /** Additional annotations about the tool. */ + @JsonProperty("annotations") @ExcludeMissing fun _annotations(): JsonValue = annotations + + /** + * The description of the tool. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun description(): Optional = description.getOptional("description") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description + + @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 [Tool]. + * + * The following fields are required: + * ```java + * .inputSchema() + * .name() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Tool]. */ + class Builder internal constructor() { + + private var inputSchema: JsonValue? = null + private var name: JsonField? = null + private var annotations: JsonValue = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(tool: Tool) = apply { + inputSchema = tool.inputSchema + name = tool.name + annotations = tool.annotations + description = tool.description + additionalProperties = tool.additionalProperties.toMutableMap() + } + + /** The JSON schema describing the tool's input. */ + fun inputSchema(inputSchema: JsonValue) = apply { this.inputSchema = inputSchema } + + /** The name of the tool. */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** Additional annotations about the tool. */ + fun annotations(annotations: JsonValue) = apply { this.annotations = annotations } + + /** The description of the tool. */ + fun description(description: String?) = + description(JsonField.ofNullable(description)) + + /** Alias for calling [Builder.description] with `description.orElse(null)`. */ + fun description(description: Optional) = + description(description.getOrNull()) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun description(description: JsonField) = apply { + this.description = description + } + + 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 [Tool]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .inputSchema() + * .name() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Tool = + Tool( + checkRequired("inputSchema", inputSchema), + checkRequired("name", name), + annotations, + description, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Tool = apply { + if (validated) { + return@apply + } + + name() + description() + 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 (name.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Tool && + inputSchema == other.inputSchema && + name == other.name && + annotations == other.annotations && + description == other.description && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(inputSchema, name, annotations, description, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Tool{inputSchema=$inputSchema, name=$name, annotations=$annotations, description=$description, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is McpListTools && + id == other.id && + serverLabel == other.serverLabel && + tools == other.tools && + type == other.type && + error == other.error && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(id, serverLabel, tools, type, error, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "McpListTools{id=$id, serverLabel=$serverLabel, tools=$tools, type=$type, error=$error, additionalProperties=$additionalProperties}" + } + + /** A request for human approval of a tool invocation. */ + class McpApprovalRequest + private constructor( + private val id: JsonField, + private val arguments: JsonField, + private val name: JsonField, + private val serverLabel: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("arguments") + @ExcludeMissing + arguments: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("server_label") + @ExcludeMissing + serverLabel: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(id, arguments, name, serverLabel, type, mutableMapOf()) + + /** + * The unique ID of the approval request. + * + * @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 id(): String = id.getRequired("id") + + /** + * A JSON string of arguments for the tool. + * + * @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 arguments(): String = arguments.getRequired("arguments") + + /** + * The name of the tool to run. + * + * @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 name(): String = name.getRequired("name") + + /** + * The label of the MCP server making the request. + * + * @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 serverLabel(): String = serverLabel.getRequired("server_label") + + /** + * The type of the item. Always `mcp_approval_request`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("mcp_approval_request") + * ``` + * + * 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 + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [arguments]. + * + * Unlike [arguments], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("arguments") @ExcludeMissing fun _arguments(): JsonField = arguments + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [serverLabel]. + * + * Unlike [serverLabel], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("server_label") + @ExcludeMissing + fun _serverLabel(): JsonField = serverLabel + + @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 [McpApprovalRequest]. + * + * The following fields are required: + * ```java + * .id() + * .arguments() + * .name() + * .serverLabel() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [McpApprovalRequest]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var arguments: JsonField? = null + private var name: JsonField? = null + private var serverLabel: JsonField? = null + private var type: JsonValue = JsonValue.from("mcp_approval_request") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(mcpApprovalRequest: McpApprovalRequest) = apply { + id = mcpApprovalRequest.id + arguments = mcpApprovalRequest.arguments + name = mcpApprovalRequest.name + serverLabel = mcpApprovalRequest.serverLabel + type = mcpApprovalRequest.type + additionalProperties = mcpApprovalRequest.additionalProperties.toMutableMap() + } + + /** The unique ID of the approval request. */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** A JSON string of arguments for the tool. */ + fun arguments(arguments: String) = arguments(JsonField.of(arguments)) + + /** + * Sets [Builder.arguments] to an arbitrary JSON value. + * + * You should usually call [Builder.arguments] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun arguments(arguments: JsonField) = apply { this.arguments = arguments } + + /** The name of the tool to run. */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** The label of the MCP server making the request. */ + fun serverLabel(serverLabel: String) = serverLabel(JsonField.of(serverLabel)) + + /** + * Sets [Builder.serverLabel] to an arbitrary JSON value. + * + * You should usually call [Builder.serverLabel] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun serverLabel(serverLabel: JsonField) = apply { + this.serverLabel = serverLabel + } + + /** + * 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("mcp_approval_request") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + 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 [McpApprovalRequest]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .arguments() + * .name() + * .serverLabel() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): McpApprovalRequest = + McpApprovalRequest( + checkRequired("id", id), + checkRequired("arguments", arguments), + checkRequired("name", name), + checkRequired("serverLabel", serverLabel), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): McpApprovalRequest = apply { + if (validated) { + return@apply + } + + id() + arguments() + name() + serverLabel() + _type().let { + if (it != JsonValue.from("mcp_approval_request")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + 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 (id.asKnown().isPresent) 1 else 0) + + (if (arguments.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (if (serverLabel.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("mcp_approval_request")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is McpApprovalRequest && + id == other.id && + arguments == other.arguments && + name == other.name && + serverLabel == other.serverLabel && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(id, arguments, name, serverLabel, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "McpApprovalRequest{id=$id, arguments=$arguments, name=$name, serverLabel=$serverLabel, type=$type, additionalProperties=$additionalProperties}" + } + + /** A response to an MCP approval request. */ + class McpApprovalResponse + private constructor( + private val id: JsonField, + private val approvalRequestId: JsonField, + private val approve: JsonField, + private val type: JsonValue, + private val reason: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("approval_request_id") + @ExcludeMissing + approvalRequestId: JsonField = JsonMissing.of(), + @JsonProperty("approve") @ExcludeMissing approve: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("reason") @ExcludeMissing reason: JsonField = JsonMissing.of(), + ) : this(id, approvalRequestId, approve, type, reason, mutableMapOf()) + + /** + * The unique ID of the approval response + * + * @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 id(): String = id.getRequired("id") + + /** + * The ID of the approval request being answered. + * + * @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 approvalRequestId(): String = approvalRequestId.getRequired("approval_request_id") + + /** + * Whether the request was approved. + * + * @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 approve(): Boolean = approve.getRequired("approve") + + /** + * The type of the item. Always `mcp_approval_response`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("mcp_approval_response") + * ``` + * + * 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 + + /** + * Optional reason for the decision. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun reason(): Optional = reason.getOptional("reason") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [approvalRequestId]. + * + * Unlike [approvalRequestId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("approval_request_id") + @ExcludeMissing + fun _approvalRequestId(): JsonField = approvalRequestId + + /** + * Returns the raw JSON value of [approve]. + * + * Unlike [approve], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("approve") @ExcludeMissing fun _approve(): JsonField = approve + + /** + * Returns the raw JSON value of [reason]. + * + * Unlike [reason], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason") @ExcludeMissing fun _reason(): JsonField = reason + + @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 [McpApprovalResponse]. + * + * The following fields are required: + * ```java + * .id() + * .approvalRequestId() + * .approve() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [McpApprovalResponse]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var approvalRequestId: JsonField? = null + private var approve: JsonField? = null + private var type: JsonValue = JsonValue.from("mcp_approval_response") + private var reason: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(mcpApprovalResponse: McpApprovalResponse) = apply { + id = mcpApprovalResponse.id + approvalRequestId = mcpApprovalResponse.approvalRequestId + approve = mcpApprovalResponse.approve + type = mcpApprovalResponse.type + reason = mcpApprovalResponse.reason + additionalProperties = mcpApprovalResponse.additionalProperties.toMutableMap() + } + + /** The unique ID of the approval response */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** The ID of the approval request being answered. */ + fun approvalRequestId(approvalRequestId: String) = + approvalRequestId(JsonField.of(approvalRequestId)) + + /** + * Sets [Builder.approvalRequestId] to an arbitrary JSON value. + * + * You should usually call [Builder.approvalRequestId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun approvalRequestId(approvalRequestId: JsonField) = apply { + this.approvalRequestId = approvalRequestId + } + + /** Whether the request was approved. */ + fun approve(approve: Boolean) = approve(JsonField.of(approve)) + + /** + * Sets [Builder.approve] to an arbitrary JSON value. + * + * You should usually call [Builder.approve] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun approve(approve: JsonField) = apply { this.approve = approve } + + /** + * 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("mcp_approval_response") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** Optional reason for the decision. */ + fun reason(reason: String?) = reason(JsonField.ofNullable(reason)) + + /** Alias for calling [Builder.reason] with `reason.orElse(null)`. */ + fun reason(reason: Optional) = reason(reason.getOrNull()) + + /** + * Sets [Builder.reason] to an arbitrary JSON value. + * + * You should usually call [Builder.reason] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun reason(reason: JsonField) = apply { this.reason = reason } + + 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 [McpApprovalResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .approvalRequestId() + * .approve() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): McpApprovalResponse = + McpApprovalResponse( + checkRequired("id", id), + checkRequired("approvalRequestId", approvalRequestId), + checkRequired("approve", approve), + type, + reason, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): McpApprovalResponse = apply { + if (validated) { + return@apply + } + + id() + approvalRequestId() + approve() + _type().let { + if (it != JsonValue.from("mcp_approval_response")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + reason() + 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 (id.asKnown().isPresent) 1 else 0) + + (if (approvalRequestId.asKnown().isPresent) 1 else 0) + + (if (approve.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("mcp_approval_response")) 1 else 0 } + + (if (reason.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is McpApprovalResponse && + id == other.id && + approvalRequestId == other.approvalRequestId && + approve == other.approve && + type == other.type && + reason == other.reason && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(id, approvalRequestId, approve, type, reason, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "McpApprovalResponse{id=$id, approvalRequestId=$approvalRequestId, approve=$approve, type=$type, reason=$reason, additionalProperties=$additionalProperties}" + } + + /** An invocation of a tool on an MCP server. */ + class McpCall + private constructor( + private val id: JsonField, + private val arguments: JsonField, + private val name: JsonField, + private val serverLabel: JsonField, + private val type: JsonValue, + private val error: JsonField, + private val output: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("arguments") + @ExcludeMissing + arguments: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("server_label") + @ExcludeMissing + serverLabel: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("error") @ExcludeMissing error: JsonField = JsonMissing.of(), + @JsonProperty("output") @ExcludeMissing output: JsonField = JsonMissing.of(), + ) : this(id, arguments, name, serverLabel, type, error, output, mutableMapOf()) + + /** + * The unique ID of the tool call. + * + * @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 id(): String = id.getRequired("id") + + /** + * A JSON string of the arguments passed to the tool. + * + * @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 arguments(): String = arguments.getRequired("arguments") + + /** + * The name of the tool that was run. + * + * @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 name(): String = name.getRequired("name") + + /** + * The label of the MCP server running the tool. + * + * @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 serverLabel(): String = serverLabel.getRequired("server_label") + + /** + * The type of the item. Always `mcp_call`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("mcp_call") + * ``` + * + * 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 + + /** + * The error from the tool call, if any. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun error(): Optional = error.getOptional("error") + + /** + * The output from the tool call. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun output(): Optional = output.getOptional("output") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [arguments]. + * + * Unlike [arguments], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("arguments") @ExcludeMissing fun _arguments(): JsonField = arguments + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [serverLabel]. + * + * Unlike [serverLabel], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("server_label") + @ExcludeMissing + fun _serverLabel(): JsonField = serverLabel + + /** + * Returns the raw JSON value of [error]. + * + * Unlike [error], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("error") @ExcludeMissing fun _error(): JsonField = error + + /** + * Returns the raw JSON value of [output]. + * + * Unlike [output], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("output") @ExcludeMissing fun _output(): JsonField = output + + @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 [McpCall]. + * + * The following fields are required: + * ```java + * .id() + * .arguments() + * .name() + * .serverLabel() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [McpCall]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var arguments: JsonField? = null + private var name: JsonField? = null + private var serverLabel: JsonField? = null + private var type: JsonValue = JsonValue.from("mcp_call") + private var error: JsonField = JsonMissing.of() + private var output: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(mcpCall: McpCall) = apply { + id = mcpCall.id + arguments = mcpCall.arguments + name = mcpCall.name + serverLabel = mcpCall.serverLabel + type = mcpCall.type + error = mcpCall.error + output = mcpCall.output + additionalProperties = mcpCall.additionalProperties.toMutableMap() + } + + /** The unique ID of the tool call. */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** A JSON string of the arguments passed to the tool. */ + fun arguments(arguments: String) = arguments(JsonField.of(arguments)) + + /** + * Sets [Builder.arguments] to an arbitrary JSON value. + * + * You should usually call [Builder.arguments] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun arguments(arguments: JsonField) = apply { this.arguments = arguments } + + /** The name of the tool that was run. */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** The label of the MCP server running the tool. */ + fun serverLabel(serverLabel: String) = serverLabel(JsonField.of(serverLabel)) + + /** + * Sets [Builder.serverLabel] to an arbitrary JSON value. + * + * You should usually call [Builder.serverLabel] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun serverLabel(serverLabel: JsonField) = apply { + this.serverLabel = serverLabel + } + + /** + * 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("mcp_call") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** The error from the tool call, if any. */ + fun error(error: String?) = error(JsonField.ofNullable(error)) + + /** Alias for calling [Builder.error] with `error.orElse(null)`. */ + fun error(error: Optional) = error(error.getOrNull()) + + /** + * Sets [Builder.error] to an arbitrary JSON value. + * + * You should usually call [Builder.error] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun error(error: JsonField) = apply { this.error = error } + + /** The output from the tool call. */ + fun output(output: String?) = output(JsonField.ofNullable(output)) + + /** Alias for calling [Builder.output] with `output.orElse(null)`. */ + fun output(output: Optional) = output(output.getOrNull()) + + /** + * Sets [Builder.output] to an arbitrary JSON value. + * + * You should usually call [Builder.output] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun output(output: JsonField) = apply { this.output = output } + + 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 [McpCall]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .arguments() + * .name() + * .serverLabel() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): McpCall = + McpCall( + checkRequired("id", id), + checkRequired("arguments", arguments), + checkRequired("name", name), + checkRequired("serverLabel", serverLabel), + type, + error, + output, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): McpCall = apply { + if (validated) { + return@apply + } + + id() + arguments() + name() + serverLabel() + _type().let { + if (it != JsonValue.from("mcp_call")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + error() + output() + 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 (id.asKnown().isPresent) 1 else 0) + + (if (arguments.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (if (serverLabel.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("mcp_call")) 1 else 0 } + + (if (error.asKnown().isPresent) 1 else 0) + + (if (output.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is McpCall && + id == other.id && + arguments == other.arguments && + name == other.name && + serverLabel == other.serverLabel && + type == other.type && + error == other.error && + output == other.output && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + id, + arguments, + name, + serverLabel, + type, + error, + output, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "McpCall{id=$id, arguments=$arguments, name=$name, serverLabel=$serverLabel, type=$type, error=$error, output=$output, additionalProperties=$additionalProperties}" + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ConversationItemList.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ConversationItemList.kt new file mode 100644 index 000000000..33b05c927 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ConversationItemList.kt @@ -0,0 +1,450 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkKnown +import com.openai.core.checkRequired +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import com.openai.models.conversations.Message +import com.openai.models.responses.ResponseCodeInterpreterToolCall +import com.openai.models.responses.ResponseComputerToolCall +import com.openai.models.responses.ResponseComputerToolCallOutputItem +import com.openai.models.responses.ResponseCustomToolCall +import com.openai.models.responses.ResponseCustomToolCallOutput +import com.openai.models.responses.ResponseFileSearchToolCall +import com.openai.models.responses.ResponseFunctionToolCallItem +import com.openai.models.responses.ResponseFunctionToolCallOutputItem +import com.openai.models.responses.ResponseFunctionWebSearch +import com.openai.models.responses.ResponseReasoningItem +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +/** A list of Conversation items. */ +class ConversationItemList +private constructor( + private val data: JsonField>, + private val firstId: JsonField, + private val hasMore: JsonField, + private val lastId: JsonField, + private val object_: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("data") + @ExcludeMissing + data: JsonField> = JsonMissing.of(), + @JsonProperty("first_id") @ExcludeMissing firstId: JsonField = JsonMissing.of(), + @JsonProperty("has_more") @ExcludeMissing hasMore: JsonField = JsonMissing.of(), + @JsonProperty("last_id") @ExcludeMissing lastId: JsonField = JsonMissing.of(), + @JsonProperty("object") @ExcludeMissing object_: JsonValue = JsonMissing.of(), + ) : this(data, firstId, hasMore, lastId, object_, mutableMapOf()) + + /** + * A list of conversation items. + * + * @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 data(): List = data.getRequired("data") + + /** + * The ID of the first item in the list. + * + * @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 firstId(): String = firstId.getRequired("first_id") + + /** + * Whether there are more items available. + * + * @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 hasMore(): Boolean = hasMore.getRequired("has_more") + + /** + * The ID of the last item in the list. + * + * @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 lastId(): String = lastId.getRequired("last_id") + + /** + * The type of object returned, must be `list`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("list") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). + */ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonValue = object_ + + /** + * Returns the raw JSON value of [data]. + * + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField> = data + + /** + * Returns the raw JSON value of [firstId]. + * + * Unlike [firstId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("first_id") @ExcludeMissing fun _firstId(): JsonField = firstId + + /** + * Returns the raw JSON value of [hasMore]. + * + * Unlike [hasMore], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("has_more") @ExcludeMissing fun _hasMore(): JsonField = hasMore + + /** + * Returns the raw JSON value of [lastId]. + * + * Unlike [lastId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("last_id") @ExcludeMissing fun _lastId(): JsonField = lastId + + @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 [ConversationItemList]. + * + * The following fields are required: + * ```java + * .data() + * .firstId() + * .hasMore() + * .lastId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConversationItemList]. */ + class Builder internal constructor() { + + private var data: JsonField>? = null + private var firstId: JsonField? = null + private var hasMore: JsonField? = null + private var lastId: JsonField? = null + private var object_: JsonValue = JsonValue.from("list") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(conversationItemList: ConversationItemList) = apply { + data = conversationItemList.data.map { it.toMutableList() } + firstId = conversationItemList.firstId + hasMore = conversationItemList.hasMore + lastId = conversationItemList.lastId + object_ = conversationItemList.object_ + additionalProperties = conversationItemList.additionalProperties.toMutableMap() + } + + /** A list of conversation items. */ + fun data(data: List) = data(JsonField.of(data)) + + /** + * Sets [Builder.data] to an arbitrary JSON value. + * + * You should usually call [Builder.data] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun data(data: JsonField>) = apply { + this.data = data.map { it.toMutableList() } + } + + /** + * Adds a single [ConversationItem] to [Builder.data]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addData(data: ConversationItem) = apply { + this.data = + (this.data ?: JsonField.of(mutableListOf())).also { + checkKnown("data", it).add(data) + } + } + + /** Alias for calling [addData] with `ConversationItem.ofMessage(message)`. */ + fun addData(message: Message) = addData(ConversationItem.ofMessage(message)) + + /** Alias for calling [addData] with `ConversationItem.ofFunctionCall(functionCall)`. */ + fun addData(functionCall: ResponseFunctionToolCallItem) = + addData(ConversationItem.ofFunctionCall(functionCall)) + + /** + * Alias for calling [addData] with + * `ConversationItem.ofFunctionCallOutput(functionCallOutput)`. + */ + fun addData(functionCallOutput: ResponseFunctionToolCallOutputItem) = + addData(ConversationItem.ofFunctionCallOutput(functionCallOutput)) + + /** Alias for calling [addData] with `ConversationItem.ofFileSearchCall(fileSearchCall)`. */ + fun addData(fileSearchCall: ResponseFileSearchToolCall) = + addData(ConversationItem.ofFileSearchCall(fileSearchCall)) + + /** Alias for calling [addData] with `ConversationItem.ofWebSearchCall(webSearchCall)`. */ + fun addData(webSearchCall: ResponseFunctionWebSearch) = + addData(ConversationItem.ofWebSearchCall(webSearchCall)) + + /** + * Alias for calling [addData] with + * `ConversationItem.ofImageGenerationCall(imageGenerationCall)`. + */ + fun addData(imageGenerationCall: ConversationItem.ImageGenerationCall) = + addData(ConversationItem.ofImageGenerationCall(imageGenerationCall)) + + /** Alias for calling [addData] with `ConversationItem.ofComputerCall(computerCall)`. */ + fun addData(computerCall: ResponseComputerToolCall) = + addData(ConversationItem.ofComputerCall(computerCall)) + + /** + * Alias for calling [addData] with + * `ConversationItem.ofComputerCallOutput(computerCallOutput)`. + */ + fun addData(computerCallOutput: ResponseComputerToolCallOutputItem) = + addData(ConversationItem.ofComputerCallOutput(computerCallOutput)) + + /** Alias for calling [addData] with `ConversationItem.ofReasoning(reasoning)`. */ + fun addData(reasoning: ResponseReasoningItem) = + addData(ConversationItem.ofReasoning(reasoning)) + + /** + * Alias for calling [addData] with + * `ConversationItem.ofCodeInterpreterCall(codeInterpreterCall)`. + */ + fun addData(codeInterpreterCall: ResponseCodeInterpreterToolCall) = + addData(ConversationItem.ofCodeInterpreterCall(codeInterpreterCall)) + + /** Alias for calling [addData] with `ConversationItem.ofLocalShellCall(localShellCall)`. */ + fun addData(localShellCall: ConversationItem.LocalShellCall) = + addData(ConversationItem.ofLocalShellCall(localShellCall)) + + /** + * Alias for calling [addData] with + * `ConversationItem.ofLocalShellCallOutput(localShellCallOutput)`. + */ + fun addData(localShellCallOutput: ConversationItem.LocalShellCallOutput) = + addData(ConversationItem.ofLocalShellCallOutput(localShellCallOutput)) + + /** Alias for calling [addData] with `ConversationItem.ofMcpListTools(mcpListTools)`. */ + fun addData(mcpListTools: ConversationItem.McpListTools) = + addData(ConversationItem.ofMcpListTools(mcpListTools)) + + /** + * Alias for calling [addData] with + * `ConversationItem.ofMcpApprovalRequest(mcpApprovalRequest)`. + */ + fun addData(mcpApprovalRequest: ConversationItem.McpApprovalRequest) = + addData(ConversationItem.ofMcpApprovalRequest(mcpApprovalRequest)) + + /** + * Alias for calling [addData] with + * `ConversationItem.ofMcpApprovalResponse(mcpApprovalResponse)`. + */ + fun addData(mcpApprovalResponse: ConversationItem.McpApprovalResponse) = + addData(ConversationItem.ofMcpApprovalResponse(mcpApprovalResponse)) + + /** Alias for calling [addData] with `ConversationItem.ofMcpCall(mcpCall)`. */ + fun addData(mcpCall: ConversationItem.McpCall) = + addData(ConversationItem.ofMcpCall(mcpCall)) + + /** Alias for calling [addData] with `ConversationItem.ofCustomToolCall(customToolCall)`. */ + fun addData(customToolCall: ResponseCustomToolCall) = + addData(ConversationItem.ofCustomToolCall(customToolCall)) + + /** + * Alias for calling [addData] with + * `ConversationItem.ofCustomToolCallOutput(customToolCallOutput)`. + */ + fun addData(customToolCallOutput: ResponseCustomToolCallOutput) = + addData(ConversationItem.ofCustomToolCallOutput(customToolCallOutput)) + + /** The ID of the first item in the list. */ + fun firstId(firstId: String) = firstId(JsonField.of(firstId)) + + /** + * Sets [Builder.firstId] to an arbitrary JSON value. + * + * You should usually call [Builder.firstId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun firstId(firstId: JsonField) = apply { this.firstId = firstId } + + /** Whether there are more items available. */ + fun hasMore(hasMore: Boolean) = hasMore(JsonField.of(hasMore)) + + /** + * Sets [Builder.hasMore] to an arbitrary JSON value. + * + * You should usually call [Builder.hasMore] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun hasMore(hasMore: JsonField) = apply { this.hasMore = hasMore } + + /** The ID of the last item in the list. */ + fun lastId(lastId: String) = lastId(JsonField.of(lastId)) + + /** + * Sets [Builder.lastId] to an arbitrary JSON value. + * + * You should usually call [Builder.lastId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun lastId(lastId: JsonField) = apply { this.lastId = lastId } + + /** + * 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("list") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun object_(object_: JsonValue) = apply { this.object_ = object_ } + + 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 [ConversationItemList]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .data() + * .firstId() + * .hasMore() + * .lastId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConversationItemList = + ConversationItemList( + checkRequired("data", data).map { it.toImmutable() }, + checkRequired("firstId", firstId), + checkRequired("hasMore", hasMore), + checkRequired("lastId", lastId), + object_, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConversationItemList = apply { + if (validated) { + return@apply + } + + data().forEach { it.validate() } + firstId() + hasMore() + lastId() + _object_().let { + if (it != JsonValue.from("list")) { + throw OpenAIInvalidDataException("'object_' is invalid, received $it") + } + } + 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 = + (data.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (firstId.asKnown().isPresent) 1 else 0) + + (if (hasMore.asKnown().isPresent) 1 else 0) + + (if (lastId.asKnown().isPresent) 1 else 0) + + object_.let { if (it == JsonValue.from("list")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConversationItemList && + data == other.data && + firstId == other.firstId && + hasMore == other.hasMore && + lastId == other.lastId && + object_ == other.object_ && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(data, firstId, hasMore, lastId, object_, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConversationItemList{data=$data, firstId=$firstId, hasMore=$hasMore, lastId=$lastId, object_=$object_, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemCreateParams.kt new file mode 100644 index 000000000..8d691e38a --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemCreateParams.kt @@ -0,0 +1,807 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.Params +import com.openai.core.checkKnown +import com.openai.core.checkRequired +import com.openai.core.http.Headers +import com.openai.core.http.QueryParams +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import com.openai.models.responses.EasyInputMessage +import com.openai.models.responses.ResponseCodeInterpreterToolCall +import com.openai.models.responses.ResponseComputerToolCall +import com.openai.models.responses.ResponseCustomToolCall +import com.openai.models.responses.ResponseCustomToolCallOutput +import com.openai.models.responses.ResponseFileSearchToolCall +import com.openai.models.responses.ResponseFunctionToolCall +import com.openai.models.responses.ResponseFunctionWebSearch +import com.openai.models.responses.ResponseIncludable +import com.openai.models.responses.ResponseInputItem +import com.openai.models.responses.ResponseOutputMessage +import com.openai.models.responses.ResponseReasoningItem +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Create items in a conversation with the given ID. */ +class ItemCreateParams +private constructor( + private val conversationId: String?, + private val include: List?, + private val body: Body, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun conversationId(): Optional = Optional.ofNullable(conversationId) + + /** + * Additional fields to include in the response. See the `include` parameter for + * [listing Conversation items above](https://platform.openai.com/docs/api-reference/conversations/list-items#conversations_list_items-include) + * for more information. + */ + fun include(): Optional> = Optional.ofNullable(include) + + /** + * The items to add to the conversation. You may add up to 20 items at a time. + * + * @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 items(): List = body.items() + + /** + * Returns the raw JSON value of [items]. + * + * Unlike [items], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _items(): JsonField> = body._items() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [ItemCreateParams]. + * + * The following fields are required: + * ```java + * .items() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ItemCreateParams]. */ + class Builder internal constructor() { + + private var conversationId: String? = null + private var include: MutableList? = null + private var body: Body.Builder = Body.builder() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(itemCreateParams: ItemCreateParams) = apply { + conversationId = itemCreateParams.conversationId + include = itemCreateParams.include?.toMutableList() + body = itemCreateParams.body.toBuilder() + additionalHeaders = itemCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = itemCreateParams.additionalQueryParams.toBuilder() + } + + fun conversationId(conversationId: String?) = apply { this.conversationId = conversationId } + + /** Alias for calling [Builder.conversationId] with `conversationId.orElse(null)`. */ + fun conversationId(conversationId: Optional) = + conversationId(conversationId.getOrNull()) + + /** + * Additional fields to include in the response. See the `include` parameter for + * [listing Conversation items above](https://platform.openai.com/docs/api-reference/conversations/list-items#conversations_list_items-include) + * for more information. + */ + fun include(include: List?) = apply { + this.include = include?.toMutableList() + } + + /** Alias for calling [Builder.include] with `include.orElse(null)`. */ + fun include(include: Optional>) = include(include.getOrNull()) + + /** + * 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 ?: mutableListOf()).apply { add(include) } + } + + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [items] + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + /** The items to add to the conversation. You may add up to 20 items at a time. */ + fun items(items: List) = apply { body.items(items) } + + /** + * Sets [Builder.items] to an arbitrary JSON value. + * + * You should usually call [Builder.items] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun items(items: JsonField>) = apply { body.items(items) } + + /** + * Adds a single [ResponseInputItem] to [items]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addItem(item: ResponseInputItem) = apply { body.addItem(item) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofEasyInputMessage(easyInputMessage)`. + */ + fun addItem(easyInputMessage: EasyInputMessage) = apply { body.addItem(easyInputMessage) } + + /** Alias for calling [addItem] with `ResponseInputItem.ofMessage(message)`. */ + fun addItem(message: ResponseInputItem.Message) = apply { body.addItem(message) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofResponseOutputMessage(responseOutputMessage)`. + */ + fun addItem(responseOutputMessage: ResponseOutputMessage) = apply { + body.addItem(responseOutputMessage) + } + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofFileSearchCall(fileSearchCall)`. + */ + fun addItem(fileSearchCall: ResponseFileSearchToolCall) = apply { + body.addItem(fileSearchCall) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofComputerCall(computerCall)`. */ + fun addItem(computerCall: ResponseComputerToolCall) = apply { body.addItem(computerCall) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofComputerCallOutput(computerCallOutput)`. + */ + fun addItem(computerCallOutput: ResponseInputItem.ComputerCallOutput) = apply { + body.addItem(computerCallOutput) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofWebSearchCall(webSearchCall)`. */ + fun addItem(webSearchCall: ResponseFunctionWebSearch) = apply { + body.addItem(webSearchCall) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofFunctionCall(functionCall)`. */ + fun addItem(functionCall: ResponseFunctionToolCall) = apply { body.addItem(functionCall) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofFunctionCallOutput(functionCallOutput)`. + */ + fun addItem(functionCallOutput: ResponseInputItem.FunctionCallOutput) = apply { + body.addItem(functionCallOutput) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofReasoning(reasoning)`. */ + fun addItem(reasoning: ResponseReasoningItem) = apply { body.addItem(reasoning) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofImageGenerationCall(imageGenerationCall)`. + */ + fun addItem(imageGenerationCall: ResponseInputItem.ImageGenerationCall) = apply { + body.addItem(imageGenerationCall) + } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofCodeInterpreterCall(codeInterpreterCall)`. + */ + fun addItem(codeInterpreterCall: ResponseCodeInterpreterToolCall) = apply { + body.addItem(codeInterpreterCall) + } + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofLocalShellCall(localShellCall)`. + */ + fun addItem(localShellCall: ResponseInputItem.LocalShellCall) = apply { + body.addItem(localShellCall) + } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofLocalShellCallOutput(localShellCallOutput)`. + */ + fun addItem(localShellCallOutput: ResponseInputItem.LocalShellCallOutput) = apply { + body.addItem(localShellCallOutput) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofMcpListTools(mcpListTools)`. */ + fun addItem(mcpListTools: ResponseInputItem.McpListTools) = apply { + body.addItem(mcpListTools) + } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofMcpApprovalRequest(mcpApprovalRequest)`. + */ + fun addItem(mcpApprovalRequest: ResponseInputItem.McpApprovalRequest) = apply { + body.addItem(mcpApprovalRequest) + } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofMcpApprovalResponse(mcpApprovalResponse)`. + */ + fun addItem(mcpApprovalResponse: ResponseInputItem.McpApprovalResponse) = apply { + body.addItem(mcpApprovalResponse) + } + + /** Alias for calling [addItem] with `ResponseInputItem.ofMcpCall(mcpCall)`. */ + fun addItem(mcpCall: ResponseInputItem.McpCall) = apply { body.addItem(mcpCall) } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofCustomToolCallOutput(customToolCallOutput)`. + */ + fun addItem(customToolCallOutput: ResponseCustomToolCallOutput) = apply { + body.addItem(customToolCallOutput) + } + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofCustomToolCall(customToolCall)`. + */ + fun addItem(customToolCall: ResponseCustomToolCall) = apply { body.addItem(customToolCall) } + + /** Alias for calling [addItem] with `ResponseInputItem.ofItemReference(itemReference)`. */ + fun addItem(itemReference: ResponseInputItem.ItemReference) = apply { + body.addItem(itemReference) + } + + /** + * Alias for calling [addItem] with the following: + * ```java + * ResponseInputItem.ItemReference.builder() + * .type(ResponseInputItem.ItemReference.Type.ITEM_REFERENCE) + * .id(id) + * .build() + * ``` + */ + fun addItemReferenceItem(id: String) = apply { body.addItemReferenceItem(id) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [ItemCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .items() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ItemCreateParams = + ItemCreateParams( + conversationId, + include?.toImmutable(), + body.build(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Body = body + + fun _pathParam(index: Int): String = + when (index) { + 0 -> conversationId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + include?.forEach { put("include[]", it.toString()) } + putAll(additionalQueryParams) + } + .build() + + class Body + private constructor( + private val items: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("items") + @ExcludeMissing + items: JsonField> = JsonMissing.of() + ) : this(items, mutableMapOf()) + + /** + * The items to add to the conversation. You may add up to 20 items at a time. + * + * @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 items(): List = items.getRequired("items") + + /** + * Returns the raw JSON value of [items]. + * + * Unlike [items], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("items") + @ExcludeMissing + fun _items(): JsonField> = items + + @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 [Body]. + * + * The following fields are required: + * ```java + * .items() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var items: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + items = body.items.map { it.toMutableList() } + additionalProperties = body.additionalProperties.toMutableMap() + } + + /** The items to add to the conversation. You may add up to 20 items at a time. */ + fun items(items: List) = items(JsonField.of(items)) + + /** + * Sets [Builder.items] to an arbitrary JSON value. + * + * You should usually call [Builder.items] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun items(items: JsonField>) = apply { + this.items = items.map { it.toMutableList() } + } + + /** + * Adds a single [ResponseInputItem] to [items]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addItem(item: ResponseInputItem) = apply { + items = + (items ?: JsonField.of(mutableListOf())).also { + checkKnown("items", it).add(item) + } + } + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofEasyInputMessage(easyInputMessage)`. + */ + fun addItem(easyInputMessage: EasyInputMessage) = + addItem(ResponseInputItem.ofEasyInputMessage(easyInputMessage)) + + /** Alias for calling [addItem] with `ResponseInputItem.ofMessage(message)`. */ + fun addItem(message: ResponseInputItem.Message) = + addItem(ResponseInputItem.ofMessage(message)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofResponseOutputMessage(responseOutputMessage)`. + */ + fun addItem(responseOutputMessage: ResponseOutputMessage) = + addItem(ResponseInputItem.ofResponseOutputMessage(responseOutputMessage)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofFileSearchCall(fileSearchCall)`. + */ + fun addItem(fileSearchCall: ResponseFileSearchToolCall) = + addItem(ResponseInputItem.ofFileSearchCall(fileSearchCall)) + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofComputerCall(computerCall)`. + */ + fun addItem(computerCall: ResponseComputerToolCall) = + addItem(ResponseInputItem.ofComputerCall(computerCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofComputerCallOutput(computerCallOutput)`. + */ + fun addItem(computerCallOutput: ResponseInputItem.ComputerCallOutput) = + addItem(ResponseInputItem.ofComputerCallOutput(computerCallOutput)) + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofWebSearchCall(webSearchCall)`. + */ + fun addItem(webSearchCall: ResponseFunctionWebSearch) = + addItem(ResponseInputItem.ofWebSearchCall(webSearchCall)) + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofFunctionCall(functionCall)`. + */ + fun addItem(functionCall: ResponseFunctionToolCall) = + addItem(ResponseInputItem.ofFunctionCall(functionCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofFunctionCallOutput(functionCallOutput)`. + */ + fun addItem(functionCallOutput: ResponseInputItem.FunctionCallOutput) = + addItem(ResponseInputItem.ofFunctionCallOutput(functionCallOutput)) + + /** Alias for calling [addItem] with `ResponseInputItem.ofReasoning(reasoning)`. */ + fun addItem(reasoning: ResponseReasoningItem) = + addItem(ResponseInputItem.ofReasoning(reasoning)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofImageGenerationCall(imageGenerationCall)`. + */ + fun addItem(imageGenerationCall: ResponseInputItem.ImageGenerationCall) = + addItem(ResponseInputItem.ofImageGenerationCall(imageGenerationCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofCodeInterpreterCall(codeInterpreterCall)`. + */ + fun addItem(codeInterpreterCall: ResponseCodeInterpreterToolCall) = + addItem(ResponseInputItem.ofCodeInterpreterCall(codeInterpreterCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofLocalShellCall(localShellCall)`. + */ + fun addItem(localShellCall: ResponseInputItem.LocalShellCall) = + addItem(ResponseInputItem.ofLocalShellCall(localShellCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofLocalShellCallOutput(localShellCallOutput)`. + */ + fun addItem(localShellCallOutput: ResponseInputItem.LocalShellCallOutput) = + addItem(ResponseInputItem.ofLocalShellCallOutput(localShellCallOutput)) + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofMcpListTools(mcpListTools)`. + */ + fun addItem(mcpListTools: ResponseInputItem.McpListTools) = + addItem(ResponseInputItem.ofMcpListTools(mcpListTools)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofMcpApprovalRequest(mcpApprovalRequest)`. + */ + fun addItem(mcpApprovalRequest: ResponseInputItem.McpApprovalRequest) = + addItem(ResponseInputItem.ofMcpApprovalRequest(mcpApprovalRequest)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofMcpApprovalResponse(mcpApprovalResponse)`. + */ + fun addItem(mcpApprovalResponse: ResponseInputItem.McpApprovalResponse) = + addItem(ResponseInputItem.ofMcpApprovalResponse(mcpApprovalResponse)) + + /** Alias for calling [addItem] with `ResponseInputItem.ofMcpCall(mcpCall)`. */ + fun addItem(mcpCall: ResponseInputItem.McpCall) = + addItem(ResponseInputItem.ofMcpCall(mcpCall)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofCustomToolCallOutput(customToolCallOutput)`. + */ + fun addItem(customToolCallOutput: ResponseCustomToolCallOutput) = + addItem(ResponseInputItem.ofCustomToolCallOutput(customToolCallOutput)) + + /** + * Alias for calling [addItem] with + * `ResponseInputItem.ofCustomToolCall(customToolCall)`. + */ + fun addItem(customToolCall: ResponseCustomToolCall) = + addItem(ResponseInputItem.ofCustomToolCall(customToolCall)) + + /** + * Alias for calling [addItem] with `ResponseInputItem.ofItemReference(itemReference)`. + */ + fun addItem(itemReference: ResponseInputItem.ItemReference) = + addItem(ResponseInputItem.ofItemReference(itemReference)) + + /** + * Alias for calling [addItem] with the following: + * ```java + * ResponseInputItem.ItemReference.builder() + * .type(ResponseInputItem.ItemReference.Type.ITEM_REFERENCE) + * .id(id) + * .build() + * ``` + */ + fun addItemReferenceItem(id: String) = + addItem( + ResponseInputItem.ItemReference.builder() + .type(ResponseInputItem.ItemReference.Type.ITEM_REFERENCE) + .id(id) + .build() + ) + + 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 [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .items() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Body = + Body( + checkRequired("items", items).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Body = apply { + if (validated) { + return@apply + } + + items().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 = + (items.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + items == other.items && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(items, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Body{items=$items, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ItemCreateParams && + conversationId == other.conversationId && + include == other.include && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(conversationId, include, body, additionalHeaders, additionalQueryParams) + + override fun toString() = + "ItemCreateParams{conversationId=$conversationId, include=$include, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemDeleteParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemDeleteParams.kt new file mode 100644 index 000000000..aa0ab50e5 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemDeleteParams.kt @@ -0,0 +1,258 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +import com.openai.core.JsonValue +import com.openai.core.Params +import com.openai.core.checkRequired +import com.openai.core.http.Headers +import com.openai.core.http.QueryParams +import com.openai.core.toImmutable +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Delete an item from a conversation with the given IDs. */ +class ItemDeleteParams +private constructor( + private val conversationId: String, + private val itemId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun conversationId(): String = conversationId + + fun itemId(): Optional = Optional.ofNullable(itemId) + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [ItemDeleteParams]. + * + * The following fields are required: + * ```java + * .conversationId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ItemDeleteParams]. */ + class Builder internal constructor() { + + private var conversationId: String? = null + private var itemId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(itemDeleteParams: ItemDeleteParams) = apply { + conversationId = itemDeleteParams.conversationId + itemId = itemDeleteParams.itemId + additionalHeaders = itemDeleteParams.additionalHeaders.toBuilder() + additionalQueryParams = itemDeleteParams.additionalQueryParams.toBuilder() + additionalBodyProperties = itemDeleteParams.additionalBodyProperties.toMutableMap() + } + + fun conversationId(conversationId: String) = apply { this.conversationId = conversationId } + + fun itemId(itemId: String?) = apply { this.itemId = itemId } + + /** Alias for calling [Builder.itemId] with `itemId.orElse(null)`. */ + fun itemId(itemId: Optional) = itemId(itemId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [ItemDeleteParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .conversationId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ItemDeleteParams = + ItemDeleteParams( + checkRequired("conversationId", conversationId), + itemId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Optional> = + Optional.ofNullable(additionalBodyProperties.ifEmpty { null }) + + fun _pathParam(index: Int): String = + when (index) { + 0 -> conversationId + 1 -> itemId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ItemDeleteParams && + conversationId == other.conversationId && + itemId == other.itemId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash( + conversationId, + itemId, + additionalHeaders, + additionalQueryParams, + additionalBodyProperties, + ) + + override fun toString() = + "ItemDeleteParams{conversationId=$conversationId, itemId=$itemId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemListPage.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemListPage.kt new file mode 100644 index 000000000..e8a278bce --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemListPage.kt @@ -0,0 +1,138 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +import com.openai.core.AutoPager +import com.openai.core.Page +import com.openai.core.checkRequired +import com.openai.services.blocking.conversations.ItemService +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** @see ItemService.list */ +class ItemListPage +private constructor( + private val service: ItemService, + private val params: ItemListParams, + private val response: ConversationItemList, +) : Page { + + /** + * Delegates to [ConversationItemList], but gracefully handles missing data. + * + * @see ConversationItemList.data + */ + fun data(): List = + response._data().getOptional("data").getOrNull() ?: emptyList() + + /** + * Delegates to [ConversationItemList], but gracefully handles missing data. + * + * @see ConversationItemList.hasMore + */ + fun hasMore(): Optional = response._hasMore().getOptional("has_more") + + /** + * Delegates to [ConversationItemList], but gracefully handles missing data. + * + * @see ConversationItemList.lastId + */ + fun lastId(): Optional = response._lastId().getOptional("last_id") + + override fun items(): List = data() + + override fun hasNextPage(): Boolean = items().isNotEmpty() && lastId().isPresent + + fun nextPageParams(): ItemListParams { + val nextCursor = + lastId().getOrNull() ?: throw IllegalStateException("Cannot construct next page params") + return params.toBuilder().after(nextCursor).build() + } + + override fun nextPage(): ItemListPage = service.list(nextPageParams()) + + fun autoPager(): AutoPager = AutoPager.from(this) + + /** The parameters that were used to request this page. */ + fun params(): ItemListParams = params + + /** The response that this page was parsed from. */ + fun response(): ConversationItemList = response + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [ItemListPage]. + * + * The following fields are required: + * ```java + * .service() + * .params() + * .response() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ItemListPage]. */ + class Builder internal constructor() { + + private var service: ItemService? = null + private var params: ItemListParams? = null + private var response: ConversationItemList? = null + + @JvmSynthetic + internal fun from(itemListPage: ItemListPage) = apply { + service = itemListPage.service + params = itemListPage.params + response = itemListPage.response + } + + fun service(service: ItemService) = apply { this.service = service } + + /** The parameters that were used to request this page. */ + fun params(params: ItemListParams) = apply { this.params = params } + + /** The response that this page was parsed from. */ + fun response(response: ConversationItemList) = apply { this.response = response } + + /** + * Returns an immutable instance of [ItemListPage]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .service() + * .params() + * .response() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ItemListPage = + ItemListPage( + checkRequired("service", service), + checkRequired("params", params), + checkRequired("response", response), + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ItemListPage && + service == other.service && + params == other.params && + response == other.response + } + + override fun hashCode(): Int = Objects.hash(service, params, response) + + override fun toString() = "ItemListPage{service=$service, params=$params, response=$response}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemListPageAsync.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemListPageAsync.kt new file mode 100644 index 000000000..7d9b61990 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemListPageAsync.kt @@ -0,0 +1,153 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +import com.openai.core.AutoPagerAsync +import com.openai.core.PageAsync +import com.openai.core.checkRequired +import com.openai.services.async.conversations.ItemServiceAsync +import java.util.Objects +import java.util.Optional +import java.util.concurrent.CompletableFuture +import java.util.concurrent.Executor +import kotlin.jvm.optionals.getOrNull + +/** @see ItemServiceAsync.list */ +class ItemListPageAsync +private constructor( + private val service: ItemServiceAsync, + private val streamHandlerExecutor: Executor, + private val params: ItemListParams, + private val response: ConversationItemList, +) : PageAsync { + + /** + * Delegates to [ConversationItemList], but gracefully handles missing data. + * + * @see ConversationItemList.data + */ + fun data(): List = + response._data().getOptional("data").getOrNull() ?: emptyList() + + /** + * Delegates to [ConversationItemList], but gracefully handles missing data. + * + * @see ConversationItemList.hasMore + */ + fun hasMore(): Optional = response._hasMore().getOptional("has_more") + + /** + * Delegates to [ConversationItemList], but gracefully handles missing data. + * + * @see ConversationItemList.lastId + */ + fun lastId(): Optional = response._lastId().getOptional("last_id") + + override fun items(): List = data() + + override fun hasNextPage(): Boolean = items().isNotEmpty() && lastId().isPresent + + fun nextPageParams(): ItemListParams { + val nextCursor = + lastId().getOrNull() ?: throw IllegalStateException("Cannot construct next page params") + return params.toBuilder().after(nextCursor).build() + } + + override fun nextPage(): CompletableFuture = service.list(nextPageParams()) + + fun autoPager(): AutoPagerAsync = + AutoPagerAsync.from(this, streamHandlerExecutor) + + /** The parameters that were used to request this page. */ + fun params(): ItemListParams = params + + /** The response that this page was parsed from. */ + fun response(): ConversationItemList = response + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [ItemListPageAsync]. + * + * The following fields are required: + * ```java + * .service() + * .streamHandlerExecutor() + * .params() + * .response() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ItemListPageAsync]. */ + class Builder internal constructor() { + + private var service: ItemServiceAsync? = null + private var streamHandlerExecutor: Executor? = null + private var params: ItemListParams? = null + private var response: ConversationItemList? = null + + @JvmSynthetic + internal fun from(itemListPageAsync: ItemListPageAsync) = apply { + service = itemListPageAsync.service + streamHandlerExecutor = itemListPageAsync.streamHandlerExecutor + params = itemListPageAsync.params + response = itemListPageAsync.response + } + + fun service(service: ItemServiceAsync) = apply { this.service = service } + + fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { + this.streamHandlerExecutor = streamHandlerExecutor + } + + /** The parameters that were used to request this page. */ + fun params(params: ItemListParams) = apply { this.params = params } + + /** The response that this page was parsed from. */ + fun response(response: ConversationItemList) = apply { this.response = response } + + /** + * Returns an immutable instance of [ItemListPageAsync]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .service() + * .streamHandlerExecutor() + * .params() + * .response() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ItemListPageAsync = + ItemListPageAsync( + checkRequired("service", service), + checkRequired("streamHandlerExecutor", streamHandlerExecutor), + checkRequired("params", params), + checkRequired("response", response), + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ItemListPageAsync && + service == other.service && + streamHandlerExecutor == other.streamHandlerExecutor && + params == other.params && + response == other.response + } + + override fun hashCode(): Int = Objects.hash(service, streamHandlerExecutor, params, response) + + override fun toString() = + "ItemListPageAsync{service=$service, streamHandlerExecutor=$streamHandlerExecutor, params=$params, response=$response}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemListParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemListParams.kt new file mode 100644 index 000000000..80db3e570 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemListParams.kt @@ -0,0 +1,464 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +import com.fasterxml.jackson.annotation.JsonCreator +import com.openai.core.Enum +import com.openai.core.JsonField +import com.openai.core.Params +import com.openai.core.http.Headers +import com.openai.core.http.QueryParams +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import com.openai.models.responses.ResponseIncludable +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** List all items for a conversation with the given ID. */ +class ItemListParams +private constructor( + private val conversationId: String?, + private val after: String?, + private val include: List?, + private val limit: Long?, + private val order: Order?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun conversationId(): Optional = Optional.ofNullable(conversationId) + + /** An item ID to list items after, used in pagination. */ + fun after(): Optional = Optional.ofNullable(after) + + /** + * Specify additional output data to include in the model response. Currently supported values + * are: + * - `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(): Optional> = Optional.ofNullable(include) + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + * default is 20. + */ + fun limit(): Optional = Optional.ofNullable(limit) + + /** + * The order to return the input items in. Default is `desc`. + * - `asc`: Return the input items in ascending order. + * - `desc`: Return the input items in descending order. + */ + fun order(): Optional = Optional.ofNullable(order) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): ItemListParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [ItemListParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ItemListParams]. */ + class Builder internal constructor() { + + private var conversationId: String? = null + private var after: String? = null + private var include: MutableList? = null + private var limit: Long? = null + private var order: Order? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(itemListParams: ItemListParams) = apply { + conversationId = itemListParams.conversationId + after = itemListParams.after + include = itemListParams.include?.toMutableList() + limit = itemListParams.limit + order = itemListParams.order + additionalHeaders = itemListParams.additionalHeaders.toBuilder() + additionalQueryParams = itemListParams.additionalQueryParams.toBuilder() + } + + fun conversationId(conversationId: String?) = apply { this.conversationId = conversationId } + + /** Alias for calling [Builder.conversationId] with `conversationId.orElse(null)`. */ + fun conversationId(conversationId: Optional) = + conversationId(conversationId.getOrNull()) + + /** An item ID to list items after, used in pagination. */ + fun after(after: String?) = apply { this.after = after } + + /** Alias for calling [Builder.after] with `after.orElse(null)`. */ + fun after(after: Optional) = after(after.getOrNull()) + + /** + * Specify additional output data to include in the model response. Currently supported + * values are: + * - `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?) = apply { + this.include = include?.toMutableList() + } + + /** Alias for calling [Builder.include] with `include.orElse(null)`. */ + fun include(include: Optional>) = include(include.getOrNull()) + + /** + * 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 ?: mutableListOf()).apply { add(include) } + } + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * Alias for [Builder.limit]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun limit(limit: Long) = limit(limit as Long?) + + /** Alias for calling [Builder.limit] with `limit.orElse(null)`. */ + fun limit(limit: Optional) = limit(limit.getOrNull()) + + /** + * The order to return the input items in. Default is `desc`. + * - `asc`: Return the input items in ascending order. + * - `desc`: Return the input items in descending order. + */ + fun order(order: Order?) = apply { this.order = order } + + /** Alias for calling [Builder.order] with `order.orElse(null)`. */ + fun order(order: Optional) = order(order.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [ItemListParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): ItemListParams = + ItemListParams( + conversationId, + after, + include?.toImmutable(), + limit, + order, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> conversationId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + after?.let { put("after", it) } + include?.forEach { put("include[]", it.toString()) } + limit?.let { put("limit", it.toString()) } + order?.let { put("order", it.toString()) } + putAll(additionalQueryParams) + } + .build() + + /** + * The order to return the input items in. Default is `desc`. + * - `asc`: Return the input items in ascending order. + * - `desc`: Return the input items in descending order. + */ + class Order @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 ASC = of("asc") + + @JvmField val DESC = of("desc") + + @JvmStatic fun of(value: String) = Order(JsonField.of(value)) + } + + /** An enum containing [Order]'s known values. */ + enum class Known { + ASC, + DESC, + } + + /** + * An enum containing [Order]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Order] 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 { + ASC, + DESC, + /** An enum member indicating that [Order] 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) { + ASC -> Value.ASC + DESC -> Value.DESC + 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) { + ASC -> Known.ASC + DESC -> Known.DESC + else -> throw OpenAIInvalidDataException("Unknown Order: $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(): Order = 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 Order && 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 ItemListParams && + conversationId == other.conversationId && + after == other.after && + include == other.include && + limit == other.limit && + order == other.order && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + conversationId, + after, + include, + limit, + order, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "ItemListParams{conversationId=$conversationId, after=$after, include=$include, limit=$limit, order=$order, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemRetrieveParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemRetrieveParams.kt new file mode 100644 index 000000000..6c2755989 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemRetrieveParams.kt @@ -0,0 +1,258 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +import com.openai.core.Params +import com.openai.core.checkRequired +import com.openai.core.http.Headers +import com.openai.core.http.QueryParams +import com.openai.core.toImmutable +import com.openai.models.responses.ResponseIncludable +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Get a single item from a conversation with the given IDs. */ +class ItemRetrieveParams +private constructor( + private val conversationId: String, + private val itemId: String?, + private val include: List?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun conversationId(): String = conversationId + + fun itemId(): Optional = Optional.ofNullable(itemId) + + /** + * Additional fields to include in the response. See the `include` parameter for + * [listing Conversation items above](https://platform.openai.com/docs/api-reference/conversations/list-items#conversations_list_items-include) + * for more information. + */ + fun include(): Optional> = Optional.ofNullable(include) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [ItemRetrieveParams]. + * + * The following fields are required: + * ```java + * .conversationId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ItemRetrieveParams]. */ + class Builder internal constructor() { + + private var conversationId: String? = null + private var itemId: String? = null + private var include: MutableList? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(itemRetrieveParams: ItemRetrieveParams) = apply { + conversationId = itemRetrieveParams.conversationId + itemId = itemRetrieveParams.itemId + include = itemRetrieveParams.include?.toMutableList() + additionalHeaders = itemRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = itemRetrieveParams.additionalQueryParams.toBuilder() + } + + fun conversationId(conversationId: String) = apply { this.conversationId = conversationId } + + fun itemId(itemId: String?) = apply { this.itemId = itemId } + + /** Alias for calling [Builder.itemId] with `itemId.orElse(null)`. */ + fun itemId(itemId: Optional) = itemId(itemId.getOrNull()) + + /** + * Additional fields to include in the response. See the `include` parameter for + * [listing Conversation items above](https://platform.openai.com/docs/api-reference/conversations/list-items#conversations_list_items-include) + * for more information. + */ + fun include(include: List?) = apply { + this.include = include?.toMutableList() + } + + /** Alias for calling [Builder.include] with `include.orElse(null)`. */ + fun include(include: Optional>) = include(include.getOrNull()) + + /** + * 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 ?: mutableListOf()).apply { add(include) } + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [ItemRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .conversationId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ItemRetrieveParams = + ItemRetrieveParams( + checkRequired("conversationId", conversationId), + itemId, + include?.toImmutable(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> conversationId + 1 -> itemId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + include?.forEach { put("include[]", it.toString()) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ItemRetrieveParams && + conversationId == other.conversationId && + itemId == other.itemId && + include == other.include && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(conversationId, itemId, include, additionalHeaders, additionalQueryParams) + + override fun toString() = + "ItemRetrieveParams{conversationId=$conversationId, itemId=$itemId, include=$include, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/CreateEvalCompletionsRunDataSource.kt b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/CreateEvalCompletionsRunDataSource.kt index b4a640398..facc6cc31 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/CreateEvalCompletionsRunDataSource.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/CreateEvalCompletionsRunDataSource.kt @@ -2374,9 +2374,9 @@ private constructor( fun addTemplate(easyInputMessage: EasyInputMessage) = addTemplate(InnerTemplate.ofEasyInputMessage(easyInputMessage)) - /** Alias for calling [addTemplate] with `InnerTemplate.ofMessage(message)`. */ - fun addTemplate(message: InnerTemplate.Message) = - addTemplate(InnerTemplate.ofMessage(message)) + /** Alias for calling [addTemplate] with `InnerTemplate.ofEvalItem(evalItem)`. */ + fun addTemplate(evalItem: InnerTemplate.EvalItem) = + addTemplate(InnerTemplate.ofEvalItem(evalItem)) /** * Sets the field to an arbitrary JSON value. @@ -2480,7 +2480,7 @@ private constructor( class InnerTemplate private constructor( private val easyInputMessage: EasyInputMessage? = null, - private val message: Message? = null, + private val evalItem: EvalItem? = null, private val _json: JsonValue? = null, ) { @@ -2501,11 +2501,11 @@ private constructor( * `assistant` role are presumed to have been generated by the model in previous * interactions. */ - fun message(): Optional = Optional.ofNullable(message) + fun evalItem(): Optional = Optional.ofNullable(evalItem) fun isEasyInputMessage(): Boolean = easyInputMessage != null - fun isMessage(): Boolean = message != null + fun isEvalItem(): Boolean = evalItem != null /** * A message input to the model with a role indicating instruction following @@ -2524,14 +2524,14 @@ private constructor( * `assistant` role are presumed to have been generated by the model in previous * interactions. */ - fun asMessage(): Message = message.getOrThrow("message") + fun asEvalItem(): EvalItem = evalItem.getOrThrow("evalItem") fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = when { easyInputMessage != null -> visitor.visitEasyInputMessage(easyInputMessage) - message != null -> visitor.visitMessage(message) + evalItem != null -> visitor.visitEvalItem(evalItem) else -> visitor.unknown(_json) } @@ -2548,8 +2548,8 @@ private constructor( easyInputMessage.validate() } - override fun visitMessage(message: Message) { - message.validate() + override fun visitEvalItem(evalItem: EvalItem) { + evalItem.validate() } } ) @@ -2577,7 +2577,7 @@ private constructor( override fun visitEasyInputMessage(easyInputMessage: EasyInputMessage) = easyInputMessage.validity() - override fun visitMessage(message: Message) = message.validity() + override fun visitEvalItem(evalItem: EvalItem) = evalItem.validity() override fun unknown(json: JsonValue?) = 0 } @@ -2590,16 +2590,16 @@ private constructor( return other is InnerTemplate && easyInputMessage == other.easyInputMessage && - message == other.message + evalItem == other.evalItem } - override fun hashCode(): Int = Objects.hash(easyInputMessage, message) + override fun hashCode(): Int = Objects.hash(easyInputMessage, evalItem) override fun toString(): String = when { easyInputMessage != null -> "InnerTemplate{easyInputMessage=$easyInputMessage}" - message != null -> "InnerTemplate{message=$message}" + evalItem != null -> "InnerTemplate{evalItem=$evalItem}" _json != null -> "InnerTemplate{_unknown=$_json}" else -> throw IllegalStateException("Invalid InnerTemplate") } @@ -2624,7 +2624,8 @@ private constructor( * `assistant` role are presumed to have been generated by the model in previous * interactions. */ - @JvmStatic fun ofMessage(message: Message) = InnerTemplate(message = message) + @JvmStatic + fun ofEvalItem(evalItem: EvalItem) = InnerTemplate(evalItem = evalItem) } /** @@ -2649,7 +2650,7 @@ private constructor( * `assistant` role are presumed to have been generated by the model in previous * interactions. */ - fun visitMessage(message: Message): T + fun visitEvalItem(evalItem: EvalItem): T /** * Maps an unknown variant of [InnerTemplate] to a value of type [T]. @@ -2671,37 +2672,30 @@ private constructor( override fun ObjectCodec.deserialize(node: JsonNode): InnerTemplate { val json = JsonValue.fromJsonNode(node) - val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() - - if (type == "message") { - val bestMatches = - sequenceOf( - tryDeserialize(node, jacksonTypeRef()) - ?.let { - InnerTemplate(easyInputMessage = it, _json = json) - }, - tryDeserialize(node, jacksonTypeRef())?.let { - InnerTemplate(message = 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 -> InnerTemplate(_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() - } - } - return InnerTemplate(_json = json) + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + InnerTemplate(easyInputMessage = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + InnerTemplate(evalItem = 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 -> InnerTemplate(_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() + } } } @@ -2715,7 +2709,7 @@ private constructor( when { value.easyInputMessage != null -> generator.writeObject(value.easyInputMessage) - value.message != null -> generator.writeObject(value.message) + value.evalItem != null -> generator.writeObject(value.evalItem) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid InnerTemplate") } @@ -2729,7 +2723,7 @@ private constructor( * `assistant` role are presumed to have been generated by the model in previous * interactions. */ - class Message + class EvalItem private constructor( private val content: JsonField, private val role: JsonField, @@ -2818,7 +2812,7 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of [Message]. + * Returns a mutable builder for constructing an instance of [EvalItem]. * * The following fields are required: * ```java @@ -2829,7 +2823,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [Message]. */ + /** A builder for [EvalItem]. */ class Builder internal constructor() { private var content: JsonField? = null @@ -2839,11 +2833,11 @@ private constructor( mutableMapOf() @JvmSynthetic - internal fun from(message: Message) = apply { - content = message.content - role = message.role - type = message.type - additionalProperties = message.additionalProperties.toMutableMap() + internal fun from(evalItem: EvalItem) = apply { + content = evalItem.content + role = evalItem.role + type = evalItem.type + additionalProperties = evalItem.additionalProperties.toMutableMap() } /** Inputs to the model - can contain template strings. */ @@ -2939,7 +2933,7 @@ private constructor( } /** - * Returns an immutable instance of [Message]. + * Returns an immutable instance of [EvalItem]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -2951,8 +2945,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): Message = - Message( + fun build(): EvalItem = + EvalItem( checkRequired("content", content), checkRequired("role", role), type, @@ -2962,7 +2956,7 @@ private constructor( private var validated: Boolean = false - fun validate(): Message = apply { + fun validate(): EvalItem = apply { if (validated) { return@apply } @@ -4105,7 +4099,7 @@ private constructor( return true } - return other is Message && + return other is EvalItem && content == other.content && role == other.role && type == other.type && @@ -4119,7 +4113,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Message{content=$content, role=$role, type=$type, additionalProperties=$additionalProperties}" + "EvalItem{content=$content, role=$role, type=$type, additionalProperties=$additionalProperties}" } } diff --git a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCancelResponse.kt b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCancelResponse.kt index 0051dac8e..b252b7382 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCancelResponse.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCancelResponse.kt @@ -6221,6 +6221,17 @@ private constructor( /** 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)`. */ diff --git a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCreateParams.kt index f456e7991..184fe6a96 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCreateParams.kt @@ -6106,6 +6106,17 @@ private constructor( /** 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)`. */ diff --git a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCreateResponse.kt b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCreateResponse.kt index 77bf6f5e3..9225f4505 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCreateResponse.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunCreateResponse.kt @@ -6221,6 +6221,17 @@ private constructor( /** 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)`. */ diff --git a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunListResponse.kt b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunListResponse.kt index 890b7483b..ea0151454 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunListResponse.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunListResponse.kt @@ -6221,6 +6221,17 @@ private constructor( /** 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)`. */ diff --git a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunRetrieveResponse.kt b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunRetrieveResponse.kt index 85834d37c..5d7a76543 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunRetrieveResponse.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/evals/runs/RunRetrieveResponse.kt @@ -6221,6 +6221,17 @@ private constructor( /** 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)`. */ 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 f2372772c..2ada2fd81 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 @@ -51,6 +51,7 @@ private constructor( private val tools: JsonField>, private val topP: JsonField, private val background: JsonField, + private val conversation: JsonField, private val maxOutputTokens: JsonField, private val maxToolCalls: JsonField, private val previousResponseId: JsonField, @@ -99,6 +100,9 @@ private constructor( @JsonProperty("background") @ExcludeMissing background: JsonField = JsonMissing.of(), + @JsonProperty("conversation") + @ExcludeMissing + conversation: JsonField = JsonMissing.of(), @JsonProperty("max_output_tokens") @ExcludeMissing maxOutputTokens: JsonField = JsonMissing.of(), @@ -153,6 +157,7 @@ private constructor( tools, topP, background, + conversation, maxOutputTokens, maxToolCalls, previousResponseId, @@ -331,6 +336,15 @@ private constructor( */ fun background(): Optional = background.getOptional("background") + /** + * The conversation that this response belongs to. Input items and output items from this + * response are automatically added to this conversation. + * + * @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") + /** * An upper bound for the number of tokens that can be generated for a response, including * visible output tokens and @@ -354,7 +368,8 @@ private constructor( /** * 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). + * [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). @@ -597,6 +612,15 @@ private constructor( */ @JsonProperty("background") @ExcludeMissing fun _background(): JsonField = background + /** + * 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 [maxOutputTokens]. * @@ -769,6 +793,7 @@ private constructor( private var tools: JsonField>? = null private var topP: JsonField? = null private var background: JsonField = JsonMissing.of() + private var conversation: JsonField = JsonMissing.of() private var maxOutputTokens: JsonField = JsonMissing.of() private var maxToolCalls: JsonField = JsonMissing.of() private var previousResponseId: JsonField = JsonMissing.of() @@ -802,6 +827,7 @@ private constructor( tools = response.tools.map { it.toMutableList() } topP = response.topP background = response.background + conversation = response.conversation maxOutputTokens = response.maxOutputTokens maxToolCalls = response.maxToolCalls previousResponseId = response.previousResponseId @@ -1211,6 +1237,17 @@ private constructor( /** 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)) @@ -1316,6 +1353,28 @@ private constructor( */ fun background(background: JsonField) = apply { this.background = background } + /** + * The conversation that this response belongs to. Input items and output items from this + * response are automatically added to this conversation. + */ + 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 + } + /** * An upper bound for the number of tokens that can be generated for a response, including * visible output tokens and @@ -1375,7 +1434,8 @@ private constructor( /** * 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). + * [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)) @@ -1676,6 +1736,7 @@ private constructor( checkRequired("tools", tools).map { it.toImmutable() }, checkRequired("topP", topP), background, + conversation, maxOutputTokens, maxToolCalls, previousResponseId, @@ -1720,6 +1781,7 @@ private constructor( tools().forEach { it.validate() } topP() background() + conversation().ifPresent { it.validate() } maxOutputTokens() maxToolCalls() previousResponseId() @@ -1767,6 +1829,7 @@ private constructor( (tools.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (topP.asKnown().isPresent) 1 else 0) + (if (background.asKnown().isPresent) 1 else 0) + + (conversation.asKnown().getOrNull()?.validity() ?: 0) + (if (maxOutputTokens.asKnown().isPresent) 1 else 0) + (if (maxToolCalls.asKnown().isPresent) 1 else 0) + (if (previousResponseId.asKnown().isPresent) 1 else 0) + @@ -2709,6 +2772,164 @@ private constructor( } } + /** + * The conversation that this response belongs to. Input items and output items from this + * response are automatically added to this conversation. + */ + class Conversation + private constructor( + private val id: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of() + ) : this(id, mutableMapOf()) + + /** + * The unique ID of the conversation. + * + * @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 id(): String = id.getRequired("id") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + @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 [Conversation]. + * + * The following fields are required: + * ```java + * .id() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Conversation]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(conversation: Conversation) = apply { + id = conversation.id + additionalProperties = conversation.additionalProperties.toMutableMap() + } + + /** The unique ID of the conversation. */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + 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 [Conversation]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Conversation = + Conversation(checkRequired("id", id), additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Conversation = apply { + if (validated) { + return@apply + } + + id() + 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 (id.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Conversation && + id == other.id && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Conversation{id=$id, additionalProperties=$additionalProperties}" + } + /** * 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 @@ -3026,6 +3247,7 @@ private constructor( tools == other.tools && topP == other.topP && background == other.background && + conversation == other.conversation && maxOutputTokens == other.maxOutputTokens && maxToolCalls == other.maxToolCalls && previousResponseId == other.previousResponseId && @@ -3060,6 +3282,7 @@ private constructor( tools, topP, background, + conversation, maxOutputTokens, maxToolCalls, previousResponseId, @@ -3081,5 +3304,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Response{id=$id, createdAt=$createdAt, error=$error, incompleteDetails=$incompleteDetails, instructions=$instructions, metadata=$metadata, model=$model, object_=$object_, output=$output, parallelToolCalls=$parallelToolCalls, temperature=$temperature, toolChoice=$toolChoice, tools=$tools, topP=$topP, background=$background, maxOutputTokens=$maxOutputTokens, maxToolCalls=$maxToolCalls, previousResponseId=$previousResponseId, prompt=$prompt, promptCacheKey=$promptCacheKey, reasoning=$reasoning, safetyIdentifier=$safetyIdentifier, serviceTier=$serviceTier, status=$status, text=$text, topLogprobs=$topLogprobs, truncation=$truncation, usage=$usage, user=$user, additionalProperties=$additionalProperties}" + "Response{id=$id, createdAt=$createdAt, error=$error, incompleteDetails=$incompleteDetails, instructions=$instructions, metadata=$metadata, model=$model, object_=$object_, output=$output, parallelToolCalls=$parallelToolCalls, temperature=$temperature, toolChoice=$toolChoice, tools=$tools, topP=$topP, background=$background, conversation=$conversation, maxOutputTokens=$maxOutputTokens, maxToolCalls=$maxToolCalls, previousResponseId=$previousResponseId, prompt=$prompt, promptCacheKey=$promptCacheKey, reasoning=$reasoning, safetyIdentifier=$safetyIdentifier, serviceTier=$serviceTier, status=$status, text=$text, topLogprobs=$topLogprobs, truncation=$truncation, usage=$usage, user=$user, additionalProperties=$additionalProperties}" } diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseConversationParam.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseConversationParam.kt new file mode 100644 index 000000000..573025a3e --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseConversationParam.kt @@ -0,0 +1,170 @@ +// 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.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +/** The conversation that this response belongs to. */ +class ResponseConversationParam +private constructor( + private val id: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of() + ) : this(id, mutableMapOf()) + + /** + * The unique ID of the conversation. + * + * @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 id(): String = id.getRequired("id") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + @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 [ResponseConversationParam]. + * + * The following fields are required: + * ```java + * .id() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ResponseConversationParam]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(responseConversationParam: ResponseConversationParam) = apply { + id = responseConversationParam.id + additionalProperties = responseConversationParam.additionalProperties.toMutableMap() + } + + /** The unique ID of the conversation. */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + 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 [ResponseConversationParam]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ResponseConversationParam = + ResponseConversationParam(checkRequired("id", id), additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): ResponseConversationParam = apply { + if (validated) { + return@apply + } + + id() + 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 (id.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ResponseConversationParam && + id == other.id && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ResponseConversationParam{id=$id, additionalProperties=$additionalProperties}" +} 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 f97259124..3573ba456 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 @@ -65,6 +65,16 @@ private constructor( */ fun background(): Optional = body.background() + /** + * 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 = body.conversation() + /** * Specify additional output data to include in the model response. Currently supported values * are: @@ -166,7 +176,8 @@ private constructor( /** * 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). + * [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). @@ -353,6 +364,13 @@ private constructor( */ fun _background(): JsonField = body._background() + /** + * Returns the raw JSON value of [conversation]. + * + * Unlike [conversation], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _conversation(): JsonField = body._conversation() + /** * Returns the raw JSON value of [include]. * @@ -562,10 +580,10 @@ private constructor( * This is generally only useful if you are already constructing the body separately. * Otherwise, it's more convenient to use the top-level setters instead: * - [background] + * - [conversation] * - [include] * - [input] * - [instructions] - * - [maxOutputTokens] * - etc. */ fun body(body: Body) = apply { this.body = body.toBuilder() } @@ -595,6 +613,39 @@ private constructor( */ fun background(background: JsonField) = apply { body.background(background) } + /** + * 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?) = apply { body.conversation(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 { + body.conversation(conversation) + } + + /** Alias for calling [conversation] with `Conversation.ofId(id)`. */ + fun conversation(id: String) = apply { body.conversation(id) } + + /** + * Alias for calling [conversation] with + * `Conversation.ofResponseConversationParam(responseConversationParam)`. + */ + fun conversation(responseConversationParam: ResponseConversationParam) = apply { + body.conversation(responseConversationParam) + } + /** * Specify additional output data to include in the model response. Currently supported * values are: @@ -819,7 +870,8 @@ private constructor( /** * 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). + * [conversation state](https://platform.openai.com/docs/guides/conversation-state). Cannot + * be used in conjunction with `conversation`. */ fun previousResponseId(previousResponseId: String?) = apply { body.previousResponseId(previousResponseId) @@ -1167,6 +1219,16 @@ private constructor( /** Alias for calling [addTool] with `Tool.ofMcp(mcp)`. */ fun addTool(mcp: Tool.Mcp) = apply { body.addTool(mcp) } + /** + * Alias for calling [addTool] with the following: + * ```java + * Tool.Mcp.builder() + * .serverLabel(serverLabel) + * .build() + * ``` + */ + fun addMcpTool(serverLabel: String) = apply { body.addMcpTool(serverLabel) } + /** Alias for calling [addTool] with `Tool.ofCodeInterpreter(codeInterpreter)`. */ fun addTool(codeInterpreter: Tool.CodeInterpreter) = apply { body.addTool(codeInterpreter) } @@ -1445,6 +1507,7 @@ private constructor( class Body private constructor( private val background: JsonField, + private val conversation: JsonField, private val include: JsonField>, private val input: JsonField, private val instructions: JsonField, @@ -1477,6 +1540,9 @@ private constructor( @JsonProperty("background") @ExcludeMissing background: JsonField = JsonMissing.of(), + @JsonProperty("conversation") + @ExcludeMissing + conversation: JsonField = JsonMissing.of(), @JsonProperty("include") @ExcludeMissing include: JsonField> = JsonMissing.of(), @@ -1541,6 +1607,7 @@ private constructor( @JsonProperty("user") @ExcludeMissing user: JsonField = JsonMissing.of(), ) : this( background, + conversation, include, input, instructions, @@ -1577,6 +1644,16 @@ private constructor( */ fun background(): Optional = background.getOptional("background") + /** + * 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: @@ -1681,7 +1758,8 @@ private constructor( /** * 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). + * [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). @@ -1872,6 +1950,16 @@ private constructor( @ExcludeMissing fun _background(): JsonField = background + /** + * 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]. * @@ -2103,6 +2191,7 @@ private constructor( class Builder internal constructor() { private var background: JsonField = JsonMissing.of() + private var conversation: JsonField = JsonMissing.of() private var include: JsonField>? = null private var input: JsonField = JsonMissing.of() private var instructions: JsonField = JsonMissing.of() @@ -2132,6 +2221,7 @@ private constructor( @JvmSynthetic internal fun from(body: Body) = apply { background = body.background + conversation = body.conversation include = body.include.map { it.toMutableList() } input = body.input instructions = body.instructions @@ -2184,6 +2274,40 @@ private constructor( */ fun background(background: JsonField) = apply { this.background = background } + /** + * 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: @@ -2421,6 +2545,7 @@ private constructor( * 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)) @@ -2744,6 +2869,17 @@ private constructor( /** 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)) @@ -2921,6 +3057,7 @@ private constructor( fun build(): Body = Body( background, + conversation, (include ?: JsonMissing.of()).map { it.toImmutable() }, input, instructions, @@ -2957,6 +3094,7 @@ private constructor( } background() + conversation().ifPresent { it.validate() } include().ifPresent { it.forEach { it.validate() } } input().ifPresent { it.validate() } instructions() @@ -3001,6 +3139,7 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (if (background.asKnown().isPresent) 1 else 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) + @@ -3033,6 +3172,7 @@ private constructor( return other is Body && background == other.background && + conversation == other.conversation && include == other.include && input == other.input && instructions == other.instructions && @@ -3063,6 +3203,7 @@ private constructor( private val hashCode: Int by lazy { Objects.hash( background, + conversation, include, input, instructions, @@ -3094,7 +3235,207 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Body{background=$background, include=$include, input=$input, instructions=$instructions, maxOutputTokens=$maxOutputTokens, maxToolCalls=$maxToolCalls, metadata=$metadata, model=$model, parallelToolCalls=$parallelToolCalls, previousResponseId=$previousResponseId, prompt=$prompt, promptCacheKey=$promptCacheKey, reasoning=$reasoning, safetyIdentifier=$safetyIdentifier, serviceTier=$serviceTier, store=$store, streamOptions=$streamOptions, temperature=$temperature, text=$text, toolChoice=$toolChoice, tools=$tools, topLogprobs=$topLogprobs, topP=$topP, truncation=$truncation, user=$user, additionalProperties=$additionalProperties}" + "Body{background=$background, conversation=$conversation, include=$include, input=$input, instructions=$instructions, maxOutputTokens=$maxOutputTokens, maxToolCalls=$maxToolCalls, metadata=$metadata, model=$model, parallelToolCalls=$parallelToolCalls, previousResponseId=$previousResponseId, prompt=$prompt, promptCacheKey=$promptCacheKey, reasoning=$reasoning, safetyIdentifier=$safetyIdentifier, serviceTier=$serviceTier, store=$store, streamOptions=$streamOptions, temperature=$temperature, text=$text, toolChoice=$toolChoice, tools=$tools, topLogprobs=$topLogprobs, topP=$topP, truncation=$truncation, user=$user, additionalProperties=$additionalProperties}" + } + + /** + * 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 array). + 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") + } + } + } } /** diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponse.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponse.kt index 7c10b1380..191525570 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponse.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponse.kt @@ -112,6 +112,9 @@ class StructuredResponse( /** @see Response.background */ fun background(): Optional = rawResponse.background() + /** @see Response.conversation */ + fun conversation(): Optional = rawResponse.conversation() + /** @see Response._id */ fun _id(): JsonField = rawResponse._id() @@ -197,6 +200,9 @@ class StructuredResponse( /** @see Response._background */ fun _background(): JsonField = rawResponse._background() + /** @see Response._conversation() */ + fun _conversation(): JsonField = rawResponse._conversation() + /** @see Response._additionalProperties */ fun _additionalProperties(): Map = rawResponse._additionalProperties() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponseCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponseCreateParams.kt index 74f4a0a62..67f0dbb52 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponseCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponseCreateParams.kt @@ -106,6 +106,29 @@ class StructuredResponseCreateParams( paramsBuilder.background(background) } + /** @see ResponseCreateParams.Builder.conversation */ + fun conversation(conversation: ResponseCreateParams.Conversation?) = apply { + paramsBuilder.conversation(conversation) + } + + /** @see ResponseCreateParams.Builder.conversation */ + fun conversation(conversation: Optional) = apply { + paramsBuilder.conversation(conversation) + } + + /** @see ResponseCreateParams.Builder.conversation */ + fun conversation(conversation: JsonField) = apply { + paramsBuilder.conversation(conversation) + } + + /** @see ResponseCreateParams.Builder.conversation */ + fun conversation(id: String) = apply { paramsBuilder.conversation(id) } + + /** @see ResponseCreateParams.Builder.conversation */ + fun conversation(responseConversationParam: ResponseConversationParam) = apply { + paramsBuilder.conversation(responseConversationParam) + } + /** @see ResponseCreateParams.Builder.include */ fun include(include: List?) = apply { paramsBuilder.include(include) } @@ -387,6 +410,9 @@ class StructuredResponseCreateParams( /** @see ResponseCreateParams.Builder.addTool */ fun addTool(mcp: Tool.Mcp) = apply { paramsBuilder.addTool(mcp) } + /** @see ResponseCreateParams.Builder.addMcpTool */ + fun addMcpTool(serverLabel: String) = apply { paramsBuilder.addMcpTool(serverLabel) } + /** @see ResponseCreateParams.Builder.addTool */ fun addTool(codeInterpreter: Tool.CodeInterpreter) = apply { paramsBuilder.addTool(codeInterpreter) diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/Tool.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/Tool.kt index 68918fa28..7456cacfc 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/responses/Tool.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/Tool.kt @@ -521,12 +521,14 @@ private constructor( class Mcp private constructor( private val serverLabel: JsonField, - private val serverUrl: JsonField, private val type: JsonValue, private val allowedTools: JsonField, + private val authorization: JsonField, + private val connectorId: JsonField, private val headers: JsonField, private val requireApproval: JsonField, private val serverDescription: JsonField, + private val serverUrl: JsonField, private val additionalProperties: MutableMap, ) { @@ -535,13 +537,16 @@ private constructor( @JsonProperty("server_label") @ExcludeMissing serverLabel: JsonField = JsonMissing.of(), - @JsonProperty("server_url") - @ExcludeMissing - serverUrl: JsonField = JsonMissing.of(), @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), @JsonProperty("allowed_tools") @ExcludeMissing allowedTools: JsonField = JsonMissing.of(), + @JsonProperty("authorization") + @ExcludeMissing + authorization: JsonField = JsonMissing.of(), + @JsonProperty("connector_id") + @ExcludeMissing + connectorId: JsonField = JsonMissing.of(), @JsonProperty("headers") @ExcludeMissing headers: JsonField = JsonMissing.of(), @JsonProperty("require_approval") @ExcludeMissing @@ -549,14 +554,19 @@ private constructor( @JsonProperty("server_description") @ExcludeMissing serverDescription: JsonField = JsonMissing.of(), + @JsonProperty("server_url") + @ExcludeMissing + serverUrl: JsonField = JsonMissing.of(), ) : this( serverLabel, - serverUrl, type, allowedTools, + authorization, + connectorId, headers, requireApproval, serverDescription, + serverUrl, mutableMapOf(), ) @@ -568,14 +578,6 @@ private constructor( */ fun serverLabel(): String = serverLabel.getRequired("server_label") - /** - * The URL for the MCP server. - * - * @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 serverUrl(): String = serverUrl.getRequired("server_url") - /** * The type of the MCP tool. Always `mcp`. * @@ -597,6 +599,36 @@ private constructor( */ fun allowedTools(): Optional = allowedTools.getOptional("allowed_tools") + /** + * An OAuth access token that can be used with a remote MCP server, either with a custom MCP + * server URL or a service connector. Your application must handle the OAuth authorization + * flow and provide the token here. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun authorization(): Optional = authorization.getOptional("authorization") + + /** + * Identifier for service connectors, like those available in ChatGPT. One of `server_url` + * or `connector_id` must be provided. Learn more about service connectors + * [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors). + * + * Currently supported `connector_id` values are: + * - Dropbox: `connector_dropbox` + * - Gmail: `connector_gmail` + * - Google Calendar: `connector_googlecalendar` + * - Google Drive: `connector_googledrive` + * - Microsoft Teams: `connector_microsoftteams` + * - Outlook Calendar: `connector_outlookcalendar` + * - Outlook Email: `connector_outlookemail` + * - SharePoint: `connector_sharepoint` + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun connectorId(): Optional = connectorId.getOptional("connector_id") + /** * Optional HTTP headers to send to the MCP server. Use for authentication or other * purposes. @@ -624,6 +656,14 @@ private constructor( fun serverDescription(): Optional = serverDescription.getOptional("server_description") + /** + * The URL for the MCP server. One of `server_url` or `connector_id` must be provided. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun serverUrl(): Optional = serverUrl.getOptional("server_url") + /** * Returns the raw JSON value of [serverLabel]. * @@ -633,13 +673,6 @@ private constructor( @ExcludeMissing fun _serverLabel(): JsonField = serverLabel - /** - * Returns the raw JSON value of [serverUrl]. - * - * Unlike [serverUrl], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("server_url") @ExcludeMissing fun _serverUrl(): JsonField = serverUrl - /** * Returns the raw JSON value of [allowedTools]. * @@ -650,6 +683,25 @@ private constructor( @ExcludeMissing fun _allowedTools(): JsonField = allowedTools + /** + * Returns the raw JSON value of [authorization]. + * + * Unlike [authorization], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("authorization") + @ExcludeMissing + fun _authorization(): JsonField = authorization + + /** + * Returns the raw JSON value of [connectorId]. + * + * Unlike [connectorId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("connector_id") + @ExcludeMissing + fun _connectorId(): JsonField = connectorId + /** * Returns the raw JSON value of [headers]. * @@ -677,6 +729,13 @@ private constructor( @ExcludeMissing fun _serverDescription(): JsonField = serverDescription + /** + * Returns the raw JSON value of [serverUrl]. + * + * Unlike [serverUrl], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("server_url") @ExcludeMissing fun _serverUrl(): JsonField = serverUrl + @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -697,7 +756,6 @@ private constructor( * The following fields are required: * ```java * .serverLabel() - * .serverUrl() * ``` */ @JvmStatic fun builder() = Builder() @@ -707,23 +765,27 @@ private constructor( class Builder internal constructor() { private var serverLabel: JsonField? = null - private var serverUrl: JsonField? = null private var type: JsonValue = JsonValue.from("mcp") private var allowedTools: JsonField = JsonMissing.of() + private var authorization: JsonField = JsonMissing.of() + private var connectorId: JsonField = JsonMissing.of() private var headers: JsonField = JsonMissing.of() private var requireApproval: JsonField = JsonMissing.of() private var serverDescription: JsonField = JsonMissing.of() + private var serverUrl: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(mcp: Mcp) = apply { serverLabel = mcp.serverLabel - serverUrl = mcp.serverUrl type = mcp.type allowedTools = mcp.allowedTools + authorization = mcp.authorization + connectorId = mcp.connectorId headers = mcp.headers requireApproval = mcp.requireApproval serverDescription = mcp.serverDescription + serverUrl = mcp.serverUrl additionalProperties = mcp.additionalProperties.toMutableMap() } @@ -741,18 +803,6 @@ private constructor( this.serverLabel = serverLabel } - /** The URL for the MCP server. */ - fun serverUrl(serverUrl: String) = serverUrl(JsonField.of(serverUrl)) - - /** - * Sets [Builder.serverUrl] to an arbitrary JSON value. - * - * You should usually call [Builder.serverUrl] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun serverUrl(serverUrl: JsonField) = apply { this.serverUrl = serverUrl } - /** * Sets the field to an arbitrary JSON value. * @@ -790,11 +840,56 @@ private constructor( fun allowedToolsOfMcp(mcp: List) = allowedTools(AllowedTools.ofMcp(mcp)) /** - * Alias for calling [allowedTools] with - * `AllowedTools.ofMcpAllowedToolsFilter(mcpAllowedToolsFilter)`. + * Alias for calling [allowedTools] with `AllowedTools.ofMcpToolFilter(mcpToolFilter)`. */ - fun allowedTools(mcpAllowedToolsFilter: AllowedTools.McpAllowedToolsFilter) = - allowedTools(AllowedTools.ofMcpAllowedToolsFilter(mcpAllowedToolsFilter)) + fun allowedTools(mcpToolFilter: AllowedTools.McpToolFilter) = + allowedTools(AllowedTools.ofMcpToolFilter(mcpToolFilter)) + + /** + * An OAuth access token that can be used with a remote MCP server, either with a custom + * MCP server URL or a service connector. Your application must handle the OAuth + * authorization flow and provide the token here. + */ + fun authorization(authorization: String) = authorization(JsonField.of(authorization)) + + /** + * Sets [Builder.authorization] to an arbitrary JSON value. + * + * You should usually call [Builder.authorization] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun authorization(authorization: JsonField) = apply { + this.authorization = authorization + } + + /** + * Identifier for service connectors, like those available in ChatGPT. One of + * `server_url` or `connector_id` must be provided. Learn more about service connectors + * [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors). + * + * Currently supported `connector_id` values are: + * - Dropbox: `connector_dropbox` + * - Gmail: `connector_gmail` + * - Google Calendar: `connector_googlecalendar` + * - Google Drive: `connector_googledrive` + * - Microsoft Teams: `connector_microsoftteams` + * - Outlook Calendar: `connector_outlookcalendar` + * - Outlook Email: `connector_outlookemail` + * - SharePoint: `connector_sharepoint` + */ + fun connectorId(connectorId: ConnectorId) = connectorId(JsonField.of(connectorId)) + + /** + * Sets [Builder.connectorId] to an arbitrary JSON value. + * + * You should usually call [Builder.connectorId] with a well-typed [ConnectorId] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun connectorId(connectorId: JsonField) = apply { + this.connectorId = connectorId + } /** * Optional HTTP headers to send to the MCP server. Use for authentication or other @@ -862,6 +957,20 @@ private constructor( this.serverDescription = serverDescription } + /** + * The URL for the MCP server. One of `server_url` or `connector_id` must be provided. + */ + fun serverUrl(serverUrl: String) = serverUrl(JsonField.of(serverUrl)) + + /** + * Sets [Builder.serverUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.serverUrl] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun serverUrl(serverUrl: JsonField) = apply { this.serverUrl = serverUrl } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -889,7 +998,6 @@ private constructor( * The following fields are required: * ```java * .serverLabel() - * .serverUrl() * ``` * * @throws IllegalStateException if any required field is unset. @@ -897,12 +1005,14 @@ private constructor( fun build(): Mcp = Mcp( checkRequired("serverLabel", serverLabel), - checkRequired("serverUrl", serverUrl), type, allowedTools, + authorization, + connectorId, headers, requireApproval, serverDescription, + serverUrl, additionalProperties.toMutableMap(), ) } @@ -915,16 +1025,18 @@ private constructor( } serverLabel() - serverUrl() _type().let { if (it != JsonValue.from("mcp")) { throw OpenAIInvalidDataException("'type' is invalid, received $it") } } allowedTools().ifPresent { it.validate() } + authorization() + connectorId().ifPresent { it.validate() } headers().ifPresent { it.validate() } requireApproval().ifPresent { it.validate() } serverDescription() + serverUrl() validated = true } @@ -945,12 +1057,14 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (if (serverLabel.asKnown().isPresent) 1 else 0) + - (if (serverUrl.asKnown().isPresent) 1 else 0) + type.let { if (it == JsonValue.from("mcp")) 1 else 0 } + (allowedTools.asKnown().getOrNull()?.validity() ?: 0) + + (if (authorization.asKnown().isPresent) 1 else 0) + + (connectorId.asKnown().getOrNull()?.validity() ?: 0) + (headers.asKnown().getOrNull()?.validity() ?: 0) + (requireApproval.asKnown().getOrNull()?.validity() ?: 0) + - (if (serverDescription.asKnown().isPresent) 1 else 0) + (if (serverDescription.asKnown().isPresent) 1 else 0) + + (if (serverUrl.asKnown().isPresent) 1 else 0) /** List of allowed tool names or a filter object. */ @JsonDeserialize(using = AllowedTools.Deserializer::class) @@ -958,7 +1072,7 @@ private constructor( class AllowedTools private constructor( private val mcp: List? = null, - private val mcpAllowedToolsFilter: McpAllowedToolsFilter? = null, + private val mcpToolFilter: McpToolFilter? = null, private val _json: JsonValue? = null, ) { @@ -966,27 +1080,24 @@ private constructor( fun mcp(): Optional> = Optional.ofNullable(mcp) /** A filter object to specify which tools are allowed. */ - fun mcpAllowedToolsFilter(): Optional = - Optional.ofNullable(mcpAllowedToolsFilter) + fun mcpToolFilter(): Optional = Optional.ofNullable(mcpToolFilter) fun isMcp(): Boolean = mcp != null - fun isMcpAllowedToolsFilter(): Boolean = mcpAllowedToolsFilter != null + fun isMcpToolFilter(): Boolean = mcpToolFilter != null /** A string array of allowed tool names */ fun asMcp(): List = mcp.getOrThrow("mcp") /** A filter object to specify which tools are allowed. */ - fun asMcpAllowedToolsFilter(): McpAllowedToolsFilter = - mcpAllowedToolsFilter.getOrThrow("mcpAllowedToolsFilter") + fun asMcpToolFilter(): McpToolFilter = mcpToolFilter.getOrThrow("mcpToolFilter") fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = when { mcp != null -> visitor.visitMcp(mcp) - mcpAllowedToolsFilter != null -> - visitor.visitMcpAllowedToolsFilter(mcpAllowedToolsFilter) + mcpToolFilter != null -> visitor.visitMcpToolFilter(mcpToolFilter) else -> visitor.unknown(_json) } @@ -1001,10 +1112,8 @@ private constructor( object : Visitor { override fun visitMcp(mcp: List) {} - override fun visitMcpAllowedToolsFilter( - mcpAllowedToolsFilter: McpAllowedToolsFilter - ) { - mcpAllowedToolsFilter.validate() + override fun visitMcpToolFilter(mcpToolFilter: McpToolFilter) { + mcpToolFilter.validate() } } ) @@ -1031,9 +1140,8 @@ private constructor( object : Visitor { override fun visitMcp(mcp: List) = mcp.size - override fun visitMcpAllowedToolsFilter( - mcpAllowedToolsFilter: McpAllowedToolsFilter - ) = mcpAllowedToolsFilter.validity() + override fun visitMcpToolFilter(mcpToolFilter: McpToolFilter) = + mcpToolFilter.validity() override fun unknown(json: JsonValue?) = 0 } @@ -1046,16 +1154,15 @@ private constructor( return other is AllowedTools && mcp == other.mcp && - mcpAllowedToolsFilter == other.mcpAllowedToolsFilter + mcpToolFilter == other.mcpToolFilter } - override fun hashCode(): Int = Objects.hash(mcp, mcpAllowedToolsFilter) + override fun hashCode(): Int = Objects.hash(mcp, mcpToolFilter) override fun toString(): String = when { mcp != null -> "AllowedTools{mcp=$mcp}" - mcpAllowedToolsFilter != null -> - "AllowedTools{mcpAllowedToolsFilter=$mcpAllowedToolsFilter}" + mcpToolFilter != null -> "AllowedTools{mcpToolFilter=$mcpToolFilter}" _json != null -> "AllowedTools{_unknown=$_json}" else -> throw IllegalStateException("Invalid AllowedTools") } @@ -1067,8 +1174,8 @@ private constructor( /** A filter object to specify which tools are allowed. */ @JvmStatic - fun ofMcpAllowedToolsFilter(mcpAllowedToolsFilter: McpAllowedToolsFilter) = - AllowedTools(mcpAllowedToolsFilter = mcpAllowedToolsFilter) + fun ofMcpToolFilter(mcpToolFilter: McpToolFilter) = + AllowedTools(mcpToolFilter = mcpToolFilter) } /** @@ -1081,7 +1188,7 @@ private constructor( fun visitMcp(mcp: List): T /** A filter object to specify which tools are allowed. */ - fun visitMcpAllowedToolsFilter(mcpAllowedToolsFilter: McpAllowedToolsFilter): T + fun visitMcpToolFilter(mcpToolFilter: McpToolFilter): T /** * Maps an unknown variant of [AllowedTools] to a value of type [T]. @@ -1105,8 +1212,8 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - AllowedTools(mcpAllowedToolsFilter = it, _json = json) + tryDeserialize(node, jacksonTypeRef())?.let { + AllowedTools(mcpToolFilter = it, _json = json) }, tryDeserialize(node, jacksonTypeRef>())?.let { AllowedTools(mcp = it, _json = json) @@ -1137,8 +1244,7 @@ private constructor( ) { when { value.mcp != null -> generator.writeObject(value.mcp) - value.mcpAllowedToolsFilter != null -> - generator.writeObject(value.mcpAllowedToolsFilter) + value.mcpToolFilter != null -> generator.writeObject(value.mcpToolFilter) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid AllowedTools") } @@ -1146,18 +1252,33 @@ private constructor( } /** A filter object to specify which tools are allowed. */ - class McpAllowedToolsFilter + class McpToolFilter private constructor( + private val readOnly: JsonField, private val toolNames: JsonField>, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( + @JsonProperty("read_only") + @ExcludeMissing + readOnly: JsonField = JsonMissing.of(), @JsonProperty("tool_names") @ExcludeMissing - toolNames: JsonField> = JsonMissing.of() - ) : this(toolNames, mutableMapOf()) + toolNames: JsonField> = JsonMissing.of(), + ) : this(readOnly, toolNames, mutableMapOf()) + + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP server + * is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun readOnly(): Optional = readOnly.getOptional("read_only") /** * List of allowed tool names. @@ -1167,6 +1288,16 @@ private constructor( */ fun toolNames(): Optional> = toolNames.getOptional("tool_names") + /** + * Returns the raw JSON value of [readOnly]. + * + * Unlike [readOnly], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("read_only") + @ExcludeMissing + fun _readOnly(): JsonField = readOnly + /** * Returns the raw JSON value of [toolNames]. * @@ -1192,25 +1323,42 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of - * [McpAllowedToolsFilter]. + * Returns a mutable builder for constructing an instance of [McpToolFilter]. */ @JvmStatic fun builder() = Builder() } - /** A builder for [McpAllowedToolsFilter]. */ + /** A builder for [McpToolFilter]. */ class Builder internal constructor() { + private var readOnly: JsonField = JsonMissing.of() private var toolNames: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(mcpAllowedToolsFilter: McpAllowedToolsFilter) = apply { - toolNames = mcpAllowedToolsFilter.toolNames.map { it.toMutableList() } - additionalProperties = - mcpAllowedToolsFilter.additionalProperties.toMutableMap() + internal fun from(mcpToolFilter: McpToolFilter) = apply { + readOnly = mcpToolFilter.readOnly + toolNames = mcpToolFilter.toolNames.map { it.toMutableList() } + additionalProperties = mcpToolFilter.additionalProperties.toMutableMap() } + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + */ + fun readOnly(readOnly: Boolean) = readOnly(JsonField.of(readOnly)) + + /** + * Sets [Builder.readOnly] to an arbitrary JSON value. + * + * You should usually call [Builder.readOnly] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun readOnly(readOnly: JsonField) = apply { this.readOnly = readOnly } + /** List of allowed tool names. */ fun toolNames(toolNames: List) = toolNames(JsonField.of(toolNames)) @@ -1260,12 +1408,13 @@ private constructor( } /** - * Returns an immutable instance of [McpAllowedToolsFilter]. + * Returns an immutable instance of [McpToolFilter]. * * Further updates to this [Builder] will not mutate the returned instance. */ - fun build(): McpAllowedToolsFilter = - McpAllowedToolsFilter( + fun build(): McpToolFilter = + McpToolFilter( + readOnly, (toolNames ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toMutableMap(), ) @@ -1273,11 +1422,12 @@ private constructor( private var validated: Boolean = false - fun validate(): McpAllowedToolsFilter = apply { + fun validate(): McpToolFilter = apply { if (validated) { return@apply } + readOnly() toolNames() validated = true } @@ -1297,25 +1447,212 @@ private constructor( * Used for best match union deserialization. */ @JvmSynthetic - internal fun validity(): Int = (toolNames.asKnown().getOrNull()?.size ?: 0) + internal fun validity(): Int = + (if (readOnly.asKnown().isPresent) 1 else 0) + + (toolNames.asKnown().getOrNull()?.size ?: 0) override fun equals(other: Any?): Boolean { if (this === other) { return true } - return other is McpAllowedToolsFilter && + return other is McpToolFilter && + readOnly == other.readOnly && toolNames == other.toolNames && additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { Objects.hash(toolNames, additionalProperties) } + private val hashCode: Int by lazy { + Objects.hash(readOnly, toolNames, additionalProperties) + } override fun hashCode(): Int = hashCode override fun toString() = - "McpAllowedToolsFilter{toolNames=$toolNames, additionalProperties=$additionalProperties}" + "McpToolFilter{readOnly=$readOnly, toolNames=$toolNames, additionalProperties=$additionalProperties}" + } + } + + /** + * Identifier for service connectors, like those available in ChatGPT. One of `server_url` + * or `connector_id` must be provided. Learn more about service connectors + * [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors). + * + * Currently supported `connector_id` values are: + * - Dropbox: `connector_dropbox` + * - Gmail: `connector_gmail` + * - Google Calendar: `connector_googlecalendar` + * - Google Drive: `connector_googledrive` + * - Microsoft Teams: `connector_microsoftteams` + * - Outlook Calendar: `connector_outlookcalendar` + * - Outlook Email: `connector_outlookemail` + * - SharePoint: `connector_sharepoint` + */ + class ConnectorId @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 CONNECTOR_DROPBOX = of("connector_dropbox") + + @JvmField val CONNECTOR_GMAIL = of("connector_gmail") + + @JvmField val CONNECTOR_GOOGLECALENDAR = of("connector_googlecalendar") + + @JvmField val CONNECTOR_GOOGLEDRIVE = of("connector_googledrive") + + @JvmField val CONNECTOR_MICROSOFTTEAMS = of("connector_microsoftteams") + + @JvmField val CONNECTOR_OUTLOOKCALENDAR = of("connector_outlookcalendar") + + @JvmField val CONNECTOR_OUTLOOKEMAIL = of("connector_outlookemail") + + @JvmField val CONNECTOR_SHAREPOINT = of("connector_sharepoint") + + @JvmStatic fun of(value: String) = ConnectorId(JsonField.of(value)) + } + + /** An enum containing [ConnectorId]'s known values. */ + enum class Known { + CONNECTOR_DROPBOX, + CONNECTOR_GMAIL, + CONNECTOR_GOOGLECALENDAR, + CONNECTOR_GOOGLEDRIVE, + CONNECTOR_MICROSOFTTEAMS, + CONNECTOR_OUTLOOKCALENDAR, + CONNECTOR_OUTLOOKEMAIL, + CONNECTOR_SHAREPOINT, + } + + /** + * An enum containing [ConnectorId]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ConnectorId] 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 { + CONNECTOR_DROPBOX, + CONNECTOR_GMAIL, + CONNECTOR_GOOGLECALENDAR, + CONNECTOR_GOOGLEDRIVE, + CONNECTOR_MICROSOFTTEAMS, + CONNECTOR_OUTLOOKCALENDAR, + CONNECTOR_OUTLOOKEMAIL, + CONNECTOR_SHAREPOINT, + /** + * An enum member indicating that [ConnectorId] 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) { + CONNECTOR_DROPBOX -> Value.CONNECTOR_DROPBOX + CONNECTOR_GMAIL -> Value.CONNECTOR_GMAIL + CONNECTOR_GOOGLECALENDAR -> Value.CONNECTOR_GOOGLECALENDAR + CONNECTOR_GOOGLEDRIVE -> Value.CONNECTOR_GOOGLEDRIVE + CONNECTOR_MICROSOFTTEAMS -> Value.CONNECTOR_MICROSOFTTEAMS + CONNECTOR_OUTLOOKCALENDAR -> Value.CONNECTOR_OUTLOOKCALENDAR + CONNECTOR_OUTLOOKEMAIL -> Value.CONNECTOR_OUTLOOKEMAIL + CONNECTOR_SHAREPOINT -> Value.CONNECTOR_SHAREPOINT + 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) { + CONNECTOR_DROPBOX -> Known.CONNECTOR_DROPBOX + CONNECTOR_GMAIL -> Known.CONNECTOR_GMAIL + CONNECTOR_GOOGLECALENDAR -> Known.CONNECTOR_GOOGLECALENDAR + CONNECTOR_GOOGLEDRIVE -> Known.CONNECTOR_GOOGLEDRIVE + CONNECTOR_MICROSOFTTEAMS -> Known.CONNECTOR_MICROSOFTTEAMS + CONNECTOR_OUTLOOKCALENDAR -> Known.CONNECTOR_OUTLOOKCALENDAR + CONNECTOR_OUTLOOKEMAIL -> Known.CONNECTOR_OUTLOOKEMAIL + CONNECTOR_SHAREPOINT -> Known.CONNECTOR_SHAREPOINT + else -> throw OpenAIInvalidDataException("Unknown ConnectorId: $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(): ConnectorId = 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 ConnectorId && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() } /** @@ -1434,6 +1771,10 @@ private constructor( private val _json: JsonValue? = null, ) { + /** + * Specify which of the MCP server's tools require approval. Can be `always`, `never`, + * or a filter object associated with tools that require approval. + */ fun mcpToolApprovalFilter(): Optional = Optional.ofNullable(mcpToolApprovalFilter) @@ -1449,6 +1790,10 @@ private constructor( fun isMcpToolApprovalSetting(): Boolean = mcpToolApprovalSetting != null + /** + * Specify which of the MCP server's tools require approval. Can be `always`, `never`, + * or a filter object associated with tools that require approval. + */ fun asMcpToolApprovalFilter(): McpToolApprovalFilter = mcpToolApprovalFilter.getOrThrow("mcpToolApprovalFilter") @@ -1551,6 +1896,10 @@ private constructor( companion object { + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ @JvmStatic fun ofMcpToolApprovalFilter(mcpToolApprovalFilter: McpToolApprovalFilter) = RequireApproval(mcpToolApprovalFilter = mcpToolApprovalFilter) @@ -1571,6 +1920,10 @@ private constructor( */ interface Visitor { + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ fun visitMcpToolApprovalFilter(mcpToolApprovalFilter: McpToolApprovalFilter): T /** @@ -1645,6 +1998,10 @@ private constructor( } } + /** + * Specify which of the MCP server's tools require approval. Can be `always`, `never`, + * or a filter object associated with tools that require approval. + */ class McpToolApprovalFilter private constructor( private val always: JsonField, @@ -1663,7 +2020,7 @@ private constructor( ) : this(always, never, mutableMapOf()) /** - * A list of tools that always require approval. + * A filter object to specify which tools are allowed. * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. * if the server responded with an unexpected value). @@ -1671,7 +2028,7 @@ private constructor( fun always(): Optional = always.getOptional("always") /** - * A list of tools that never require approval. + * A filter object to specify which tools are allowed. * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. * if the server responded with an unexpected value). @@ -1730,7 +2087,7 @@ private constructor( mcpToolApprovalFilter.additionalProperties.toMutableMap() } - /** A list of tools that always require approval. */ + /** A filter object to specify which tools are allowed. */ fun always(always: Always) = always(JsonField.of(always)) /** @@ -1742,7 +2099,7 @@ private constructor( */ fun always(always: JsonField) = apply { this.always = always } - /** A list of tools that never require approval. */ + /** A filter object to specify which tools are allowed. */ fun never(never: Never) = never(JsonField.of(never)) /** @@ -1816,28 +2173,53 @@ private constructor( (always.asKnown().getOrNull()?.validity() ?: 0) + (never.asKnown().getOrNull()?.validity() ?: 0) - /** A list of tools that always require approval. */ + /** A filter object to specify which tools are allowed. */ class Always private constructor( + private val readOnly: JsonField, private val toolNames: JsonField>, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( + @JsonProperty("read_only") + @ExcludeMissing + readOnly: JsonField = JsonMissing.of(), @JsonProperty("tool_names") @ExcludeMissing - toolNames: JsonField> = JsonMissing.of() - ) : this(toolNames, mutableMapOf()) + toolNames: JsonField> = JsonMissing.of(), + ) : this(readOnly, toolNames, mutableMapOf()) + + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun readOnly(): Optional = readOnly.getOptional("read_only") /** - * List of tools that require approval. + * List of allowed tool names. * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type * (e.g. if the server responded with an unexpected value). */ fun toolNames(): Optional> = toolNames.getOptional("tool_names") + /** + * Returns the raw JSON value of [readOnly]. + * + * Unlike [readOnly], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("read_only") + @ExcludeMissing + fun _readOnly(): JsonField = readOnly + /** * Returns the raw JSON value of [toolNames]. * @@ -1869,17 +2251,38 @@ private constructor( /** A builder for [Always]. */ class Builder internal constructor() { + private var readOnly: JsonField = JsonMissing.of() private var toolNames: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(always: Always) = apply { + readOnly = always.readOnly toolNames = always.toolNames.map { it.toMutableList() } additionalProperties = always.additionalProperties.toMutableMap() } - /** List of tools that require approval. */ + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + */ + fun readOnly(readOnly: Boolean) = readOnly(JsonField.of(readOnly)) + + /** + * Sets [Builder.readOnly] to an arbitrary JSON value. + * + * You should usually call [Builder.readOnly] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun readOnly(readOnly: JsonField) = apply { + this.readOnly = readOnly + } + + /** List of allowed tool names. */ fun toolNames(toolNames: List) = toolNames(JsonField.of(toolNames)) /** @@ -1935,6 +2338,7 @@ private constructor( */ fun build(): Always = Always( + readOnly, (toolNames ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toMutableMap(), ) @@ -1947,6 +2351,7 @@ private constructor( return@apply } + readOnly() toolNames() validated = true } @@ -1966,7 +2371,9 @@ private constructor( * Used for best match union deserialization. */ @JvmSynthetic - internal fun validity(): Int = (toolNames.asKnown().getOrNull()?.size ?: 0) + internal fun validity(): Int = + (if (readOnly.asKnown().isPresent) 1 else 0) + + (toolNames.asKnown().getOrNull()?.size ?: 0) override fun equals(other: Any?): Boolean { if (this === other) { @@ -1974,42 +2381,68 @@ private constructor( } return other is Always && + readOnly == other.readOnly && toolNames == other.toolNames && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(toolNames, additionalProperties) + Objects.hash(readOnly, toolNames, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "Always{toolNames=$toolNames, additionalProperties=$additionalProperties}" + "Always{readOnly=$readOnly, toolNames=$toolNames, additionalProperties=$additionalProperties}" } - /** A list of tools that never require approval. */ + /** A filter object to specify which tools are allowed. */ class Never private constructor( + private val readOnly: JsonField, private val toolNames: JsonField>, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( + @JsonProperty("read_only") + @ExcludeMissing + readOnly: JsonField = JsonMissing.of(), @JsonProperty("tool_names") @ExcludeMissing - toolNames: JsonField> = JsonMissing.of() - ) : this(toolNames, mutableMapOf()) + toolNames: JsonField> = JsonMissing.of(), + ) : this(readOnly, toolNames, mutableMapOf()) /** - * List of tools that do not require approval. + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun readOnly(): Optional = readOnly.getOptional("read_only") + + /** + * List of allowed tool names. * * @throws OpenAIInvalidDataException if the JSON field has an unexpected type * (e.g. if the server responded with an unexpected value). */ fun toolNames(): Optional> = toolNames.getOptional("tool_names") + /** + * Returns the raw JSON value of [readOnly]. + * + * Unlike [readOnly], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("read_only") + @ExcludeMissing + fun _readOnly(): JsonField = readOnly + /** * Returns the raw JSON value of [toolNames]. * @@ -2041,17 +2474,38 @@ private constructor( /** A builder for [Never]. */ class Builder internal constructor() { + private var readOnly: JsonField = JsonMissing.of() private var toolNames: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(never: Never) = apply { + readOnly = never.readOnly toolNames = never.toolNames.map { it.toMutableList() } additionalProperties = never.additionalProperties.toMutableMap() } - /** List of tools that do not require approval. */ + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + */ + fun readOnly(readOnly: Boolean) = readOnly(JsonField.of(readOnly)) + + /** + * Sets [Builder.readOnly] to an arbitrary JSON value. + * + * You should usually call [Builder.readOnly] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun readOnly(readOnly: JsonField) = apply { + this.readOnly = readOnly + } + + /** List of allowed tool names. */ fun toolNames(toolNames: List) = toolNames(JsonField.of(toolNames)) /** @@ -2107,6 +2561,7 @@ private constructor( */ fun build(): Never = Never( + readOnly, (toolNames ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toMutableMap(), ) @@ -2119,6 +2574,7 @@ private constructor( return@apply } + readOnly() toolNames() validated = true } @@ -2138,7 +2594,9 @@ private constructor( * Used for best match union deserialization. */ @JvmSynthetic - internal fun validity(): Int = (toolNames.asKnown().getOrNull()?.size ?: 0) + internal fun validity(): Int = + (if (readOnly.asKnown().isPresent) 1 else 0) + + (toolNames.asKnown().getOrNull()?.size ?: 0) override fun equals(other: Any?): Boolean { if (this === other) { @@ -2146,18 +2604,19 @@ private constructor( } return other is Never && + readOnly == other.readOnly && toolNames == other.toolNames && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(toolNames, additionalProperties) + Objects.hash(readOnly, toolNames, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "Never{toolNames=$toolNames, additionalProperties=$additionalProperties}" + "Never{readOnly=$readOnly, toolNames=$toolNames, additionalProperties=$additionalProperties}" } override fun equals(other: Any?): Boolean { @@ -2331,24 +2790,28 @@ private constructor( return other is Mcp && serverLabel == other.serverLabel && - serverUrl == other.serverUrl && type == other.type && allowedTools == other.allowedTools && + authorization == other.authorization && + connectorId == other.connectorId && headers == other.headers && requireApproval == other.requireApproval && serverDescription == other.serverDescription && + serverUrl == other.serverUrl && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { Objects.hash( serverLabel, - serverUrl, type, allowedTools, + authorization, + connectorId, headers, requireApproval, serverDescription, + serverUrl, additionalProperties, ) } @@ -2356,7 +2819,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Mcp{serverLabel=$serverLabel, serverUrl=$serverUrl, type=$type, allowedTools=$allowedTools, headers=$headers, requireApproval=$requireApproval, serverDescription=$serverDescription, additionalProperties=$additionalProperties}" + "Mcp{serverLabel=$serverLabel, type=$type, allowedTools=$allowedTools, authorization=$authorization, connectorId=$connectorId, headers=$headers, requireApproval=$requireApproval, serverDescription=$serverDescription, serverUrl=$serverUrl, additionalProperties=$additionalProperties}" } /** A tool that runs Python code to help generate a response to a prompt. */ diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/inputitems/InputItemListParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/inputitems/InputItemListParams.kt index 55df5b348..cd0564fa5 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/responses/inputitems/InputItemListParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/inputitems/InputItemListParams.kt @@ -20,7 +20,6 @@ class InputItemListParams private constructor( private val responseId: String?, private val after: String?, - private val before: String?, private val include: List?, private val limit: Long?, private val order: Order?, @@ -33,9 +32,6 @@ private constructor( /** An item ID to list items after, used in pagination. */ fun after(): Optional = Optional.ofNullable(after) - /** An item ID to list items before, used in pagination. */ - fun before(): Optional = Optional.ofNullable(before) - /** * Additional fields to include in the response. See the `include` parameter for Response * creation above for more information. @@ -76,7 +72,6 @@ private constructor( private var responseId: String? = null private var after: String? = null - private var before: String? = null private var include: MutableList? = null private var limit: Long? = null private var order: Order? = null @@ -87,7 +82,6 @@ private constructor( internal fun from(inputItemListParams: InputItemListParams) = apply { responseId = inputItemListParams.responseId after = inputItemListParams.after - before = inputItemListParams.before include = inputItemListParams.include?.toMutableList() limit = inputItemListParams.limit order = inputItemListParams.order @@ -106,12 +100,6 @@ private constructor( /** Alias for calling [Builder.after] with `after.orElse(null)`. */ fun after(after: Optional) = after(after.getOrNull()) - /** An item ID to list items before, used in pagination. */ - fun before(before: String?) = apply { this.before = before } - - /** Alias for calling [Builder.before] with `before.orElse(null)`. */ - fun before(before: Optional) = before(before.getOrNull()) - /** * Additional fields to include in the response. See the `include` parameter for Response * creation above for more information. @@ -265,7 +253,6 @@ private constructor( InputItemListParams( responseId, after, - before, include?.toImmutable(), limit, order, @@ -286,7 +273,6 @@ private constructor( QueryParams.builder() .apply { after?.let { put("after", it) } - before?.let { put("before", it) } include?.forEach { put("include[]", it.toString()) } limit?.let { put("limit", it.toString()) } order?.let { put("order", it.toString()) } @@ -432,7 +418,6 @@ private constructor( return other is InputItemListParams && responseId == other.responseId && after == other.after && - before == other.before && include == other.include && limit == other.limit && order == other.order && @@ -444,7 +429,6 @@ private constructor( Objects.hash( responseId, after, - before, include, limit, order, @@ -453,5 +437,5 @@ private constructor( ) override fun toString() = - "InputItemListParams{responseId=$responseId, after=$after, before=$before, include=$include, limit=$limit, order=$order, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "InputItemListParams{responseId=$responseId, after=$after, include=$include, limit=$limit, order=$order, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/ConversationServiceAsync.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/ConversationServiceAsync.kt new file mode 100644 index 000000000..76a76059b --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/ConversationServiceAsync.kt @@ -0,0 +1,301 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.async + +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.http.HttpResponseFor +import com.openai.models.conversations.Conversation +import com.openai.models.conversations.ConversationCreateParams +import com.openai.models.conversations.ConversationDeleteParams +import com.openai.models.conversations.ConversationDeletedResource +import com.openai.models.conversations.ConversationRetrieveParams +import com.openai.models.conversations.ConversationUpdateParams +import com.openai.services.async.conversations.ItemServiceAsync +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +interface ConversationServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): ConversationServiceAsync + + fun items(): ItemServiceAsync + + /** Create a conversation with the given ID. */ + fun create(): CompletableFuture = create(ConversationCreateParams.none()) + + /** @see create */ + fun create( + params: ConversationCreateParams = ConversationCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see create */ + fun create( + params: ConversationCreateParams = ConversationCreateParams.none() + ): CompletableFuture = create(params, RequestOptions.none()) + + /** @see create */ + fun create(requestOptions: RequestOptions): CompletableFuture = + create(ConversationCreateParams.none(), requestOptions) + + /** Get a conversation with the given ID. */ + fun retrieve(conversationId: String): CompletableFuture = + retrieve(conversationId, ConversationRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + conversationId: String, + params: ConversationRetrieveParams = ConversationRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + retrieve(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + conversationId: String, + params: ConversationRetrieveParams = ConversationRetrieveParams.none(), + ): CompletableFuture = retrieve(conversationId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: ConversationRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see retrieve */ + fun retrieve(params: ConversationRetrieveParams): CompletableFuture = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + conversationId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + retrieve(conversationId, ConversationRetrieveParams.none(), requestOptions) + + /** Update a conversation's metadata with the given ID. */ + fun update( + conversationId: String, + params: ConversationUpdateParams, + ): CompletableFuture = update(conversationId, params, RequestOptions.none()) + + /** @see update */ + fun update( + conversationId: String, + params: ConversationUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + update(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see update */ + fun update(params: ConversationUpdateParams): CompletableFuture = + update(params, RequestOptions.none()) + + /** @see update */ + fun update( + params: ConversationUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** Delete a conversation with the given ID. */ + fun delete(conversationId: String): CompletableFuture = + delete(conversationId, ConversationDeleteParams.none()) + + /** @see delete */ + fun delete( + conversationId: String, + params: ConversationDeleteParams = ConversationDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + delete(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see delete */ + fun delete( + conversationId: String, + params: ConversationDeleteParams = ConversationDeleteParams.none(), + ): CompletableFuture = + delete(conversationId, params, RequestOptions.none()) + + /** @see delete */ + fun delete( + params: ConversationDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see delete */ + fun delete(params: ConversationDeleteParams): CompletableFuture = + delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete( + conversationId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + delete(conversationId, ConversationDeleteParams.none(), requestOptions) + + /** + * A view of [ConversationServiceAsync] that provides access to raw HTTP responses for each + * method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: Consumer + ): ConversationServiceAsync.WithRawResponse + + fun items(): ItemServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post /conversations`, but is otherwise the same as + * [ConversationServiceAsync.create]. + */ + fun create(): CompletableFuture> = + create(ConversationCreateParams.none()) + + /** @see create */ + fun create( + params: ConversationCreateParams = ConversationCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see create */ + fun create( + params: ConversationCreateParams = ConversationCreateParams.none() + ): CompletableFuture> = create(params, RequestOptions.none()) + + /** @see create */ + fun create( + requestOptions: RequestOptions + ): CompletableFuture> = + create(ConversationCreateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /conversations/{conversation_id}`, but is otherwise + * the same as [ConversationServiceAsync.retrieve]. + */ + fun retrieve(conversationId: String): CompletableFuture> = + retrieve(conversationId, ConversationRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + conversationId: String, + params: ConversationRetrieveParams = ConversationRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + retrieve(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + conversationId: String, + params: ConversationRetrieveParams = ConversationRetrieveParams.none(), + ): CompletableFuture> = + retrieve(conversationId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: ConversationRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see retrieve */ + fun retrieve( + params: ConversationRetrieveParams + ): CompletableFuture> = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + conversationId: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + retrieve(conversationId, ConversationRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /conversations/{conversation_id}`, but is otherwise + * the same as [ConversationServiceAsync.update]. + */ + fun update( + conversationId: String, + params: ConversationUpdateParams, + ): CompletableFuture> = + update(conversationId, params, RequestOptions.none()) + + /** @see update */ + fun update( + conversationId: String, + params: ConversationUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + update(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see update */ + fun update( + params: ConversationUpdateParams + ): CompletableFuture> = update(params, RequestOptions.none()) + + /** @see update */ + fun update( + params: ConversationUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** + * Returns a raw HTTP response for `delete /conversations/{conversation_id}`, but is + * otherwise the same as [ConversationServiceAsync.delete]. + */ + fun delete( + conversationId: String + ): CompletableFuture> = + delete(conversationId, ConversationDeleteParams.none()) + + /** @see delete */ + fun delete( + conversationId: String, + params: ConversationDeleteParams = ConversationDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + delete(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see delete */ + fun delete( + conversationId: String, + params: ConversationDeleteParams = ConversationDeleteParams.none(), + ): CompletableFuture> = + delete(conversationId, params, RequestOptions.none()) + + /** @see delete */ + fun delete( + params: ConversationDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see delete */ + fun delete( + params: ConversationDeleteParams + ): CompletableFuture> = + delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete( + conversationId: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + delete(conversationId, ConversationDeleteParams.none(), requestOptions) + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/ConversationServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/ConversationServiceAsyncImpl.kt new file mode 100644 index 000000000..3c608ba9a --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/ConversationServiceAsyncImpl.kt @@ -0,0 +1,226 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.async + +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.checkRequired +import com.openai.core.handlers.errorBodyHandler +import com.openai.core.handlers.errorHandler +import com.openai.core.handlers.jsonHandler +import com.openai.core.http.HttpMethod +import com.openai.core.http.HttpRequest +import com.openai.core.http.HttpResponse +import com.openai.core.http.HttpResponse.Handler +import com.openai.core.http.HttpResponseFor +import com.openai.core.http.json +import com.openai.core.http.parseable +import com.openai.core.prepareAsync +import com.openai.models.conversations.Conversation +import com.openai.models.conversations.ConversationCreateParams +import com.openai.models.conversations.ConversationDeleteParams +import com.openai.models.conversations.ConversationDeletedResource +import com.openai.models.conversations.ConversationRetrieveParams +import com.openai.models.conversations.ConversationUpdateParams +import com.openai.services.async.conversations.ItemServiceAsync +import com.openai.services.async.conversations.ItemServiceAsyncImpl +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class ConversationServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + ConversationServiceAsync { + + private val withRawResponse: ConversationServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val items: ItemServiceAsync by lazy { ItemServiceAsyncImpl(clientOptions) } + + override fun withRawResponse(): ConversationServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): ConversationServiceAsync = + ConversationServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun items(): ItemServiceAsync = items + + override fun create( + params: ConversationCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /conversations + withRawResponse().create(params, requestOptions).thenApply { it.parse() } + + override fun retrieve( + params: ConversationRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /conversations/{conversation_id} + withRawResponse().retrieve(params, requestOptions).thenApply { it.parse() } + + override fun update( + params: ConversationUpdateParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /conversations/{conversation_id} + withRawResponse().update(params, requestOptions).thenApply { it.parse() } + + override fun delete( + params: ConversationDeleteParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // delete /conversations/{conversation_id} + withRawResponse().delete(params, requestOptions).thenApply { it.parse() } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + ConversationServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + private val items: ItemServiceAsync.WithRawResponse by lazy { + ItemServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: Consumer + ): ConversationServiceAsync.WithRawResponse = + ConversationServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + override fun items(): ItemServiceAsync.WithRawResponse = items + + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: ConversationCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: ConversationRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("conversationId", params.conversationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations", params._pathParam(0)) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val updateHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun update( + params: ConversationUpdateParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("conversationId", params.conversationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations", params._pathParam(0)) + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { updateHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val deleteHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun delete( + params: ConversationDeleteParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("conversationId", params.conversationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations", params._pathParam(0)) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { deleteHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/conversations/ItemServiceAsync.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/conversations/ItemServiceAsync.kt new file mode 100644 index 000000000..f024e1f1d --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/conversations/ItemServiceAsync.kt @@ -0,0 +1,275 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.async.conversations + +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.http.HttpResponseFor +import com.openai.models.conversations.Conversation +import com.openai.models.conversations.items.ConversationItem +import com.openai.models.conversations.items.ConversationItemList +import com.openai.models.conversations.items.ItemCreateParams +import com.openai.models.conversations.items.ItemDeleteParams +import com.openai.models.conversations.items.ItemListPageAsync +import com.openai.models.conversations.items.ItemListParams +import com.openai.models.conversations.items.ItemRetrieveParams +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +interface ItemServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): ItemServiceAsync + + /** Create items in a conversation with the given ID. */ + fun create( + conversationId: String, + params: ItemCreateParams, + ): CompletableFuture = + create(conversationId, params, RequestOptions.none()) + + /** @see create */ + fun create( + conversationId: String, + params: ItemCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + create(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see create */ + fun create(params: ItemCreateParams): CompletableFuture = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: ItemCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** Get a single item from a conversation with the given IDs. */ + fun retrieve(itemId: String, params: ItemRetrieveParams): CompletableFuture = + retrieve(itemId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + itemId: String, + params: ItemRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + retrieve(params.toBuilder().itemId(itemId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve(params: ItemRetrieveParams): CompletableFuture = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: ItemRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** List all items for a conversation with the given ID. */ + fun list(conversationId: String): CompletableFuture = + list(conversationId, ItemListParams.none()) + + /** @see list */ + fun list( + conversationId: String, + params: ItemListParams = ItemListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + list(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see list */ + fun list( + conversationId: String, + params: ItemListParams = ItemListParams.none(), + ): CompletableFuture = list(conversationId, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: ItemListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see list */ + fun list(params: ItemListParams): CompletableFuture = + list(params, RequestOptions.none()) + + /** @see list */ + fun list( + conversationId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + list(conversationId, ItemListParams.none(), requestOptions) + + /** Delete an item from a conversation with the given IDs. */ + fun delete(itemId: String, params: ItemDeleteParams): CompletableFuture = + delete(itemId, params, RequestOptions.none()) + + /** @see delete */ + fun delete( + itemId: String, + params: ItemDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + delete(params.toBuilder().itemId(itemId).build(), requestOptions) + + /** @see delete */ + fun delete(params: ItemDeleteParams): CompletableFuture = + delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete( + params: ItemDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** A view of [ItemServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): ItemServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post /conversations/{conversation_id}/items`, but is + * otherwise the same as [ItemServiceAsync.create]. + */ + fun create( + conversationId: String, + params: ItemCreateParams, + ): CompletableFuture> = + create(conversationId, params, RequestOptions.none()) + + /** @see create */ + fun create( + conversationId: String, + params: ItemCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + create(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see create */ + fun create( + params: ItemCreateParams + ): CompletableFuture> = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: ItemCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** + * Returns a raw HTTP response for `get /conversations/{conversation_id}/items/{item_id}`, + * but is otherwise the same as [ItemServiceAsync.retrieve]. + */ + fun retrieve( + itemId: String, + params: ItemRetrieveParams, + ): CompletableFuture> = + retrieve(itemId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + itemId: String, + params: ItemRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + retrieve(params.toBuilder().itemId(itemId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + params: ItemRetrieveParams + ): CompletableFuture> = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: ItemRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** + * Returns a raw HTTP response for `get /conversations/{conversation_id}/items`, but is + * otherwise the same as [ItemServiceAsync.list]. + */ + fun list(conversationId: String): CompletableFuture> = + list(conversationId, ItemListParams.none()) + + /** @see list */ + fun list( + conversationId: String, + params: ItemListParams = ItemListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + list(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see list */ + fun list( + conversationId: String, + params: ItemListParams = ItemListParams.none(), + ): CompletableFuture> = + list(conversationId, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: ItemListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see list */ + fun list(params: ItemListParams): CompletableFuture> = + list(params, RequestOptions.none()) + + /** @see list */ + fun list( + conversationId: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + list(conversationId, ItemListParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete + * /conversations/{conversation_id}/items/{item_id}`, but is otherwise the same as + * [ItemServiceAsync.delete]. + */ + fun delete( + itemId: String, + params: ItemDeleteParams, + ): CompletableFuture> = + delete(itemId, params, RequestOptions.none()) + + /** @see delete */ + fun delete( + itemId: String, + params: ItemDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + delete(params.toBuilder().itemId(itemId).build(), requestOptions) + + /** @see delete */ + fun delete(params: ItemDeleteParams): CompletableFuture> = + delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete( + params: ItemDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/conversations/ItemServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/conversations/ItemServiceAsyncImpl.kt new file mode 100644 index 000000000..13eef73aa --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/conversations/ItemServiceAsyncImpl.kt @@ -0,0 +1,236 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.async.conversations + +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.checkRequired +import com.openai.core.handlers.errorBodyHandler +import com.openai.core.handlers.errorHandler +import com.openai.core.handlers.jsonHandler +import com.openai.core.http.HttpMethod +import com.openai.core.http.HttpRequest +import com.openai.core.http.HttpResponse +import com.openai.core.http.HttpResponse.Handler +import com.openai.core.http.HttpResponseFor +import com.openai.core.http.json +import com.openai.core.http.parseable +import com.openai.core.prepareAsync +import com.openai.models.conversations.Conversation +import com.openai.models.conversations.items.ConversationItem +import com.openai.models.conversations.items.ConversationItemList +import com.openai.models.conversations.items.ItemCreateParams +import com.openai.models.conversations.items.ItemDeleteParams +import com.openai.models.conversations.items.ItemListPageAsync +import com.openai.models.conversations.items.ItemListParams +import com.openai.models.conversations.items.ItemRetrieveParams +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class ItemServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + ItemServiceAsync { + + private val withRawResponse: ItemServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): ItemServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): ItemServiceAsync = + ItemServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun create( + params: ItemCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /conversations/{conversation_id}/items + withRawResponse().create(params, requestOptions).thenApply { it.parse() } + + override fun retrieve( + params: ItemRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /conversations/{conversation_id}/items/{item_id} + withRawResponse().retrieve(params, requestOptions).thenApply { it.parse() } + + override fun list( + params: ItemListParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /conversations/{conversation_id}/items + withRawResponse().list(params, requestOptions).thenApply { it.parse() } + + override fun delete( + params: ItemDeleteParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // delete /conversations/{conversation_id}/items/{item_id} + withRawResponse().delete(params, requestOptions).thenApply { it.parse() } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + ItemServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): ItemServiceAsync.WithRawResponse = + ItemServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: ItemCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("conversationId", params.conversationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations", params._pathParam(0), "items") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: ItemRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("itemId", params.itemId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "conversations", + params._pathParam(0), + "items", + params._pathParam(1), + ) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val listHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun list( + params: ItemListParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("conversationId", params.conversationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations", params._pathParam(0), "items") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { listHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + .let { + ItemListPageAsync.builder() + .service(ItemServiceAsyncImpl(clientOptions)) + .streamHandlerExecutor(clientOptions.streamHandlerExecutor) + .params(params) + .response(it) + .build() + } + } + } + } + + private val deleteHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun delete( + params: ItemDeleteParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("itemId", params.itemId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "conversations", + params._pathParam(0), + "items", + params._pathParam(1), + ) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { deleteHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/ConversationService.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/ConversationService.kt new file mode 100644 index 000000000..c2d4f7ee9 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/ConversationService.kt @@ -0,0 +1,301 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.blocking + +import com.google.errorprone.annotations.MustBeClosed +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.http.HttpResponseFor +import com.openai.models.conversations.Conversation +import com.openai.models.conversations.ConversationCreateParams +import com.openai.models.conversations.ConversationDeleteParams +import com.openai.models.conversations.ConversationDeletedResource +import com.openai.models.conversations.ConversationRetrieveParams +import com.openai.models.conversations.ConversationUpdateParams +import com.openai.services.blocking.conversations.ItemService +import java.util.function.Consumer + +interface ConversationService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): ConversationService + + fun items(): ItemService + + /** Create a conversation with the given ID. */ + fun create(): Conversation = create(ConversationCreateParams.none()) + + /** @see create */ + fun create( + params: ConversationCreateParams = ConversationCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Conversation + + /** @see create */ + fun create(params: ConversationCreateParams = ConversationCreateParams.none()): Conversation = + create(params, RequestOptions.none()) + + /** @see create */ + fun create(requestOptions: RequestOptions): Conversation = + create(ConversationCreateParams.none(), requestOptions) + + /** Get a conversation with the given ID. */ + fun retrieve(conversationId: String): Conversation = + retrieve(conversationId, ConversationRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + conversationId: String, + params: ConversationRetrieveParams = ConversationRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Conversation = + retrieve(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + conversationId: String, + params: ConversationRetrieveParams = ConversationRetrieveParams.none(), + ): Conversation = retrieve(conversationId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: ConversationRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Conversation + + /** @see retrieve */ + fun retrieve(params: ConversationRetrieveParams): Conversation = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve(conversationId: String, requestOptions: RequestOptions): Conversation = + retrieve(conversationId, ConversationRetrieveParams.none(), requestOptions) + + /** Update a conversation's metadata with the given ID. */ + fun update(conversationId: String, params: ConversationUpdateParams): Conversation = + update(conversationId, params, RequestOptions.none()) + + /** @see update */ + fun update( + conversationId: String, + params: ConversationUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Conversation = + update(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see update */ + fun update(params: ConversationUpdateParams): Conversation = + update(params, RequestOptions.none()) + + /** @see update */ + fun update( + params: ConversationUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Conversation + + /** Delete a conversation with the given ID. */ + fun delete(conversationId: String): ConversationDeletedResource = + delete(conversationId, ConversationDeleteParams.none()) + + /** @see delete */ + fun delete( + conversationId: String, + params: ConversationDeleteParams = ConversationDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): ConversationDeletedResource = + delete(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see delete */ + fun delete( + conversationId: String, + params: ConversationDeleteParams = ConversationDeleteParams.none(), + ): ConversationDeletedResource = delete(conversationId, params, RequestOptions.none()) + + /** @see delete */ + fun delete( + params: ConversationDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): ConversationDeletedResource + + /** @see delete */ + fun delete(params: ConversationDeleteParams): ConversationDeletedResource = + delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete( + conversationId: String, + requestOptions: RequestOptions, + ): ConversationDeletedResource = + delete(conversationId, ConversationDeleteParams.none(), requestOptions) + + /** + * A view of [ConversationService] that provides access to raw HTTP responses for each method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: Consumer + ): ConversationService.WithRawResponse + + fun items(): ItemService.WithRawResponse + + /** + * Returns a raw HTTP response for `post /conversations`, but is otherwise the same as + * [ConversationService.create]. + */ + @MustBeClosed + fun create(): HttpResponseFor = create(ConversationCreateParams.none()) + + /** @see create */ + @MustBeClosed + fun create( + params: ConversationCreateParams = ConversationCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + fun create( + params: ConversationCreateParams = ConversationCreateParams.none() + ): HttpResponseFor = create(params, RequestOptions.none()) + + /** @see create */ + @MustBeClosed + fun create(requestOptions: RequestOptions): HttpResponseFor = + create(ConversationCreateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /conversations/{conversation_id}`, but is otherwise + * the same as [ConversationService.retrieve]. + */ + @MustBeClosed + fun retrieve(conversationId: String): HttpResponseFor = + retrieve(conversationId, ConversationRetrieveParams.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + conversationId: String, + params: ConversationRetrieveParams = ConversationRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + conversationId: String, + params: ConversationRetrieveParams = ConversationRetrieveParams.none(), + ): HttpResponseFor = retrieve(conversationId, params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: ConversationRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve(params: ConversationRetrieveParams): HttpResponseFor = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + conversationId: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + retrieve(conversationId, ConversationRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /conversations/{conversation_id}`, but is otherwise + * the same as [ConversationService.update]. + */ + @MustBeClosed + fun update( + conversationId: String, + params: ConversationUpdateParams, + ): HttpResponseFor = update(conversationId, params, RequestOptions.none()) + + /** @see update */ + @MustBeClosed + fun update( + conversationId: String, + params: ConversationUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + update(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see update */ + @MustBeClosed + fun update(params: ConversationUpdateParams): HttpResponseFor = + update(params, RequestOptions.none()) + + /** @see update */ + @MustBeClosed + fun update( + params: ConversationUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** + * Returns a raw HTTP response for `delete /conversations/{conversation_id}`, but is + * otherwise the same as [ConversationService.delete]. + */ + @MustBeClosed + fun delete(conversationId: String): HttpResponseFor = + delete(conversationId, ConversationDeleteParams.none()) + + /** @see delete */ + @MustBeClosed + fun delete( + conversationId: String, + params: ConversationDeleteParams = ConversationDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + delete(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + fun delete( + conversationId: String, + params: ConversationDeleteParams = ConversationDeleteParams.none(), + ): HttpResponseFor = + delete(conversationId, params, RequestOptions.none()) + + /** @see delete */ + @MustBeClosed + fun delete( + params: ConversationDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see delete */ + @MustBeClosed + fun delete(params: ConversationDeleteParams): HttpResponseFor = + delete(params, RequestOptions.none()) + + /** @see delete */ + @MustBeClosed + fun delete( + conversationId: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + delete(conversationId, ConversationDeleteParams.none(), requestOptions) + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/ConversationServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/ConversationServiceImpl.kt new file mode 100644 index 000000000..ebd734430 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/ConversationServiceImpl.kt @@ -0,0 +1,213 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.blocking + +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.checkRequired +import com.openai.core.handlers.errorBodyHandler +import com.openai.core.handlers.errorHandler +import com.openai.core.handlers.jsonHandler +import com.openai.core.http.HttpMethod +import com.openai.core.http.HttpRequest +import com.openai.core.http.HttpResponse +import com.openai.core.http.HttpResponse.Handler +import com.openai.core.http.HttpResponseFor +import com.openai.core.http.json +import com.openai.core.http.parseable +import com.openai.core.prepare +import com.openai.models.conversations.Conversation +import com.openai.models.conversations.ConversationCreateParams +import com.openai.models.conversations.ConversationDeleteParams +import com.openai.models.conversations.ConversationDeletedResource +import com.openai.models.conversations.ConversationRetrieveParams +import com.openai.models.conversations.ConversationUpdateParams +import com.openai.services.blocking.conversations.ItemService +import com.openai.services.blocking.conversations.ItemServiceImpl +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class ConversationServiceImpl internal constructor(private val clientOptions: ClientOptions) : + ConversationService { + + private val withRawResponse: ConversationService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val items: ItemService by lazy { ItemServiceImpl(clientOptions) } + + override fun withRawResponse(): ConversationService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): ConversationService = + ConversationServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun items(): ItemService = items + + override fun create( + params: ConversationCreateParams, + requestOptions: RequestOptions, + ): Conversation = + // post /conversations + withRawResponse().create(params, requestOptions).parse() + + override fun retrieve( + params: ConversationRetrieveParams, + requestOptions: RequestOptions, + ): Conversation = + // get /conversations/{conversation_id} + withRawResponse().retrieve(params, requestOptions).parse() + + override fun update( + params: ConversationUpdateParams, + requestOptions: RequestOptions, + ): Conversation = + // post /conversations/{conversation_id} + withRawResponse().update(params, requestOptions).parse() + + override fun delete( + params: ConversationDeleteParams, + requestOptions: RequestOptions, + ): ConversationDeletedResource = + // delete /conversations/{conversation_id} + withRawResponse().delete(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + ConversationService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + private val items: ItemService.WithRawResponse by lazy { + ItemServiceImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: Consumer + ): ConversationService.WithRawResponse = + ConversationServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + override fun items(): ItemService.WithRawResponse = items + + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: ConversationCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: ConversationRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("conversationId", params.conversationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations", params._pathParam(0)) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val updateHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun update( + params: ConversationUpdateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("conversationId", params.conversationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations", params._pathParam(0)) + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { updateHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val deleteHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun delete( + params: ConversationDeleteParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("conversationId", params.conversationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations", params._pathParam(0)) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { deleteHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/conversations/ItemService.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/conversations/ItemService.kt new file mode 100644 index 000000000..970555ffc --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/conversations/ItemService.kt @@ -0,0 +1,271 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.blocking.conversations + +import com.google.errorprone.annotations.MustBeClosed +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.http.HttpResponseFor +import com.openai.models.conversations.Conversation +import com.openai.models.conversations.items.ConversationItem +import com.openai.models.conversations.items.ConversationItemList +import com.openai.models.conversations.items.ItemCreateParams +import com.openai.models.conversations.items.ItemDeleteParams +import com.openai.models.conversations.items.ItemListPage +import com.openai.models.conversations.items.ItemListParams +import com.openai.models.conversations.items.ItemRetrieveParams +import java.util.function.Consumer + +interface ItemService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): ItemService + + /** Create items in a conversation with the given ID. */ + fun create(conversationId: String, params: ItemCreateParams): ConversationItemList = + create(conversationId, params, RequestOptions.none()) + + /** @see create */ + fun create( + conversationId: String, + params: ItemCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): ConversationItemList = + create(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see create */ + fun create(params: ItemCreateParams): ConversationItemList = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: ItemCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): ConversationItemList + + /** Get a single item from a conversation with the given IDs. */ + fun retrieve(itemId: String, params: ItemRetrieveParams): ConversationItem = + retrieve(itemId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + itemId: String, + params: ItemRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): ConversationItem = retrieve(params.toBuilder().itemId(itemId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve(params: ItemRetrieveParams): ConversationItem = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: ItemRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): ConversationItem + + /** List all items for a conversation with the given ID. */ + fun list(conversationId: String): ItemListPage = list(conversationId, ItemListParams.none()) + + /** @see list */ + fun list( + conversationId: String, + params: ItemListParams = ItemListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): ItemListPage = + list(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see list */ + fun list(conversationId: String, params: ItemListParams = ItemListParams.none()): ItemListPage = + list(conversationId, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: ItemListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): ItemListPage + + /** @see list */ + fun list(params: ItemListParams): ItemListPage = list(params, RequestOptions.none()) + + /** @see list */ + fun list(conversationId: String, requestOptions: RequestOptions): ItemListPage = + list(conversationId, ItemListParams.none(), requestOptions) + + /** Delete an item from a conversation with the given IDs. */ + fun delete(itemId: String, params: ItemDeleteParams): Conversation = + delete(itemId, params, RequestOptions.none()) + + /** @see delete */ + fun delete( + itemId: String, + params: ItemDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Conversation = delete(params.toBuilder().itemId(itemId).build(), requestOptions) + + /** @see delete */ + fun delete(params: ItemDeleteParams): Conversation = delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete( + params: ItemDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Conversation + + /** A view of [ItemService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): ItemService.WithRawResponse + + /** + * Returns a raw HTTP response for `post /conversations/{conversation_id}/items`, but is + * otherwise the same as [ItemService.create]. + */ + @MustBeClosed + fun create( + conversationId: String, + params: ItemCreateParams, + ): HttpResponseFor = + create(conversationId, params, RequestOptions.none()) + + /** @see create */ + @MustBeClosed + fun create( + conversationId: String, + params: ItemCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see create */ + @MustBeClosed + fun create(params: ItemCreateParams): HttpResponseFor = + create(params, RequestOptions.none()) + + /** @see create */ + @MustBeClosed + fun create( + params: ItemCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** + * Returns a raw HTTP response for `get /conversations/{conversation_id}/items/{item_id}`, + * but is otherwise the same as [ItemService.retrieve]. + */ + @MustBeClosed + fun retrieve( + itemId: String, + params: ItemRetrieveParams, + ): HttpResponseFor = retrieve(itemId, params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + itemId: String, + params: ItemRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().itemId(itemId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + fun retrieve(params: ItemRetrieveParams): HttpResponseFor = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: ItemRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** + * Returns a raw HTTP response for `get /conversations/{conversation_id}/items`, but is + * otherwise the same as [ItemService.list]. + */ + @MustBeClosed + fun list(conversationId: String): HttpResponseFor = + list(conversationId, ItemListParams.none()) + + /** @see list */ + @MustBeClosed + fun list( + conversationId: String, + params: ItemListParams = ItemListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + list(params.toBuilder().conversationId(conversationId).build(), requestOptions) + + /** @see list */ + @MustBeClosed + fun list( + conversationId: String, + params: ItemListParams = ItemListParams.none(), + ): HttpResponseFor = list(conversationId, params, RequestOptions.none()) + + /** @see list */ + @MustBeClosed + fun list( + params: ItemListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see list */ + @MustBeClosed + fun list(params: ItemListParams): HttpResponseFor = + list(params, RequestOptions.none()) + + /** @see list */ + @MustBeClosed + fun list( + conversationId: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + list(conversationId, ItemListParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete + * /conversations/{conversation_id}/items/{item_id}`, but is otherwise the same as + * [ItemService.delete]. + */ + @MustBeClosed + fun delete(itemId: String, params: ItemDeleteParams): HttpResponseFor = + delete(itemId, params, RequestOptions.none()) + + /** @see delete */ + @MustBeClosed + fun delete( + itemId: String, + params: ItemDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + delete(params.toBuilder().itemId(itemId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + fun delete(params: ItemDeleteParams): HttpResponseFor = + delete(params, RequestOptions.none()) + + /** @see delete */ + @MustBeClosed + fun delete( + params: ItemDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/conversations/ItemServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/conversations/ItemServiceImpl.kt new file mode 100644 index 000000000..e32e93173 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/conversations/ItemServiceImpl.kt @@ -0,0 +1,215 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.blocking.conversations + +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.checkRequired +import com.openai.core.handlers.errorBodyHandler +import com.openai.core.handlers.errorHandler +import com.openai.core.handlers.jsonHandler +import com.openai.core.http.HttpMethod +import com.openai.core.http.HttpRequest +import com.openai.core.http.HttpResponse +import com.openai.core.http.HttpResponse.Handler +import com.openai.core.http.HttpResponseFor +import com.openai.core.http.json +import com.openai.core.http.parseable +import com.openai.core.prepare +import com.openai.models.conversations.Conversation +import com.openai.models.conversations.items.ConversationItem +import com.openai.models.conversations.items.ConversationItemList +import com.openai.models.conversations.items.ItemCreateParams +import com.openai.models.conversations.items.ItemDeleteParams +import com.openai.models.conversations.items.ItemListPage +import com.openai.models.conversations.items.ItemListParams +import com.openai.models.conversations.items.ItemRetrieveParams +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class ItemServiceImpl internal constructor(private val clientOptions: ClientOptions) : ItemService { + + private val withRawResponse: ItemService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): ItemService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): ItemService = + ItemServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun create( + params: ItemCreateParams, + requestOptions: RequestOptions, + ): ConversationItemList = + // post /conversations/{conversation_id}/items + withRawResponse().create(params, requestOptions).parse() + + override fun retrieve( + params: ItemRetrieveParams, + requestOptions: RequestOptions, + ): ConversationItem = + // get /conversations/{conversation_id}/items/{item_id} + withRawResponse().retrieve(params, requestOptions).parse() + + override fun list(params: ItemListParams, requestOptions: RequestOptions): ItemListPage = + // get /conversations/{conversation_id}/items + withRawResponse().list(params, requestOptions).parse() + + override fun delete(params: ItemDeleteParams, requestOptions: RequestOptions): Conversation = + // delete /conversations/{conversation_id}/items/{item_id} + withRawResponse().delete(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + ItemService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): ItemService.WithRawResponse = + ItemServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: ItemCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("conversationId", params.conversationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations", params._pathParam(0), "items") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: ItemRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("itemId", params.itemId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "conversations", + params._pathParam(0), + "items", + params._pathParam(1), + ) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val listHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun list( + params: ItemListParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("conversationId", params.conversationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("conversations", params._pathParam(0), "items") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { listHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + .let { + ItemListPage.builder() + .service(ItemServiceImpl(clientOptions)) + .params(params) + .response(it) + .build() + } + } + } + + private val deleteHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun delete( + params: ItemDeleteParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("itemId", params.itemId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "conversations", + params._pathParam(0), + "items", + params._pathParam(1), + ) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { deleteHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/ComputerScreenshotContentTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ComputerScreenshotContentTest.kt new file mode 100644 index 000000000..02a77cc7a --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ComputerScreenshotContentTest.kt @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ComputerScreenshotContentTest { + + @Test + fun create() { + val computerScreenshotContent = + ComputerScreenshotContent.builder().fileId("file_id").imageUrl("image_url").build() + + assertThat(computerScreenshotContent.fileId()).contains("file_id") + assertThat(computerScreenshotContent.imageUrl()).contains("image_url") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val computerScreenshotContent = + ComputerScreenshotContent.builder().fileId("file_id").imageUrl("image_url").build() + + val roundtrippedComputerScreenshotContent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(computerScreenshotContent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedComputerScreenshotContent).isEqualTo(computerScreenshotContent) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/ContainerFileCitationBodyTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ContainerFileCitationBodyTest.kt new file mode 100644 index 000000000..423f51b4e --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ContainerFileCitationBodyTest.kt @@ -0,0 +1,50 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ContainerFileCitationBodyTest { + + @Test + fun create() { + val containerFileCitationBody = + ContainerFileCitationBody.builder() + .containerId("container_id") + .endIndex(0L) + .fileId("file_id") + .filename("filename") + .startIndex(0L) + .build() + + assertThat(containerFileCitationBody.containerId()).isEqualTo("container_id") + assertThat(containerFileCitationBody.endIndex()).isEqualTo(0L) + assertThat(containerFileCitationBody.fileId()).isEqualTo("file_id") + assertThat(containerFileCitationBody.filename()).isEqualTo("filename") + assertThat(containerFileCitationBody.startIndex()).isEqualTo(0L) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val containerFileCitationBody = + ContainerFileCitationBody.builder() + .containerId("container_id") + .endIndex(0L) + .fileId("file_id") + .filename("filename") + .startIndex(0L) + .build() + + val roundtrippedContainerFileCitationBody = + jsonMapper.readValue( + jsonMapper.writeValueAsString(containerFileCitationBody), + jacksonTypeRef(), + ) + + assertThat(roundtrippedContainerFileCitationBody).isEqualTo(containerFileCitationBody) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationCreateParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationCreateParamsTest.kt new file mode 100644 index 000000000..c3205144e --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationCreateParamsTest.kt @@ -0,0 +1,76 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.openai.core.JsonValue +import com.openai.models.responses.EasyInputMessage +import com.openai.models.responses.ResponseInputItem +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ConversationCreateParamsTest { + + @Test + fun create() { + ConversationCreateParams.builder() + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .type(EasyInputMessage.Type.MESSAGE) + .build() + ) + .metadata( + ConversationCreateParams.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + ConversationCreateParams.builder() + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .type(EasyInputMessage.Type.MESSAGE) + .build() + ) + .metadata( + ConversationCreateParams.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .build() + + val body = params._body() + + assertThat(body.items().getOrNull()) + .containsExactly( + ResponseInputItem.ofEasyInputMessage( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .type(EasyInputMessage.Type.MESSAGE) + .build() + ) + ) + assertThat(body.metadata()) + .contains( + ConversationCreateParams.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = ConversationCreateParams.builder().build() + + val body = params._body() + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationDeleteParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationDeleteParamsTest.kt new file mode 100644 index 000000000..fce29d249 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationDeleteParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ConversationDeleteParamsTest { + + @Test + fun create() { + ConversationDeleteParams.builder().conversationId("conv_123").build() + } + + @Test + fun pathParams() { + val params = ConversationDeleteParams.builder().conversationId("conv_123").build() + + assertThat(params._pathParam(0)).isEqualTo("conv_123") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationDeletedResourceTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationDeletedResourceTest.kt new file mode 100644 index 000000000..5a57b5ebe --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationDeletedResourceTest.kt @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ConversationDeletedResourceTest { + + @Test + fun create() { + val conversationDeletedResource = + ConversationDeletedResource.builder().id("id").deleted(true).build() + + assertThat(conversationDeletedResource.id()).isEqualTo("id") + assertThat(conversationDeletedResource.deleted()).isEqualTo(true) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val conversationDeletedResource = + ConversationDeletedResource.builder().id("id").deleted(true).build() + + val roundtrippedConversationDeletedResource = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationDeletedResource), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationDeletedResource).isEqualTo(conversationDeletedResource) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationDeletedTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationDeletedTest.kt new file mode 100644 index 000000000..c3d083eb4 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationDeletedTest.kt @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ConversationDeletedTest { + + @Test + fun create() { + val conversationDeleted = ConversationDeleted.builder().id("id").deleted(true).build() + + assertThat(conversationDeleted.id()).isEqualTo("id") + assertThat(conversationDeleted.deleted()).isEqualTo(true) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val conversationDeleted = ConversationDeleted.builder().id("id").deleted(true).build() + + val roundtrippedConversationDeleted = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationDeleted), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationDeleted).isEqualTo(conversationDeleted) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationRetrieveParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationRetrieveParamsTest.kt new file mode 100644 index 000000000..3e7bf7fd6 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationRetrieveParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ConversationRetrieveParamsTest { + + @Test + fun create() { + ConversationRetrieveParams.builder().conversationId("conv_123").build() + } + + @Test + fun pathParams() { + val params = ConversationRetrieveParams.builder().conversationId("conv_123").build() + + assertThat(params._pathParam(0)).isEqualTo("conv_123") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationTest.kt new file mode 100644 index 000000000..ed86aac97 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationTest.kt @@ -0,0 +1,45 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.JsonValue +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ConversationTest { + + @Test + fun create() { + val conversation = + Conversation.builder() + .id("id") + .createdAt(0L) + .metadata(JsonValue.from(mapOf())) + .build() + + assertThat(conversation.id()).isEqualTo("id") + assertThat(conversation.createdAt()).isEqualTo(0L) + assertThat(conversation._metadata()).isEqualTo(JsonValue.from(mapOf())) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val conversation = + Conversation.builder() + .id("id") + .createdAt(0L) + .metadata(JsonValue.from(mapOf())) + .build() + + val roundtrippedConversation = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversation), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversation).isEqualTo(conversation) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationUpdateParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationUpdateParamsTest.kt new file mode 100644 index 000000000..23bae2821 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/ConversationUpdateParamsTest.kt @@ -0,0 +1,61 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.openai.core.JsonValue +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ConversationUpdateParamsTest { + + @Test + fun create() { + ConversationUpdateParams.builder() + .conversationId("conv_123") + .metadata( + ConversationUpdateParams.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .build() + } + + @Test + fun pathParams() { + val params = + ConversationUpdateParams.builder() + .conversationId("conv_123") + .metadata( + ConversationUpdateParams.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .build() + + assertThat(params._pathParam(0)).isEqualTo("conv_123") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun body() { + val params = + ConversationUpdateParams.builder() + .conversationId("conv_123") + .metadata( + ConversationUpdateParams.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .build() + + val body = params._body() + + assertThat(body.metadata()) + .isEqualTo( + ConversationUpdateParams.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/FileCitationBodyTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/FileCitationBodyTest.kt new file mode 100644 index 000000000..62e90779e --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/FileCitationBodyTest.kt @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class FileCitationBodyTest { + + @Test + fun create() { + val fileCitationBody = + FileCitationBody.builder().fileId("file_id").filename("filename").index(0L).build() + + assertThat(fileCitationBody.fileId()).isEqualTo("file_id") + assertThat(fileCitationBody.filename()).isEqualTo("filename") + assertThat(fileCitationBody.index()).isEqualTo(0L) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val fileCitationBody = + FileCitationBody.builder().fileId("file_id").filename("filename").index(0L).build() + + val roundtrippedFileCitationBody = + jsonMapper.readValue( + jsonMapper.writeValueAsString(fileCitationBody), + jacksonTypeRef(), + ) + + assertThat(roundtrippedFileCitationBody).isEqualTo(fileCitationBody) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/InputFileContentTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/InputFileContentTest.kt new file mode 100644 index 000000000..67dc90b3f --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/InputFileContentTest.kt @@ -0,0 +1,44 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class InputFileContentTest { + + @Test + fun create() { + val inputFileContent = + InputFileContent.builder() + .fileId("file_id") + .fileUrl("file_url") + .filename("filename") + .build() + + assertThat(inputFileContent.fileId()).contains("file_id") + assertThat(inputFileContent.fileUrl()).contains("file_url") + assertThat(inputFileContent.filename()).contains("filename") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val inputFileContent = + InputFileContent.builder() + .fileId("file_id") + .fileUrl("file_url") + .filename("filename") + .build() + + val roundtrippedInputFileContent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(inputFileContent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedInputFileContent).isEqualTo(inputFileContent) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/InputImageContentTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/InputImageContentTest.kt new file mode 100644 index 000000000..6fb785fd0 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/InputImageContentTest.kt @@ -0,0 +1,44 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class InputImageContentTest { + + @Test + fun create() { + val inputImageContent = + InputImageContent.builder() + .detail(InputImageContent.Detail.LOW) + .fileId("file_id") + .imageUrl("image_url") + .build() + + assertThat(inputImageContent.detail()).isEqualTo(InputImageContent.Detail.LOW) + assertThat(inputImageContent.fileId()).contains("file_id") + assertThat(inputImageContent.imageUrl()).contains("image_url") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val inputImageContent = + InputImageContent.builder() + .detail(InputImageContent.Detail.LOW) + .fileId("file_id") + .imageUrl("image_url") + .build() + + val roundtrippedInputImageContent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(inputImageContent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedInputImageContent).isEqualTo(inputImageContent) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/InputTextContentTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/InputTextContentTest.kt new file mode 100644 index 000000000..2e1f8a103 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/InputTextContentTest.kt @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class InputTextContentTest { + + @Test + fun create() { + val inputTextContent = InputTextContent.builder().text("text").build() + + assertThat(inputTextContent.text()).isEqualTo("text") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val inputTextContent = InputTextContent.builder().text("text").build() + + val roundtrippedInputTextContent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(inputTextContent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedInputTextContent).isEqualTo(inputTextContent) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/LobProbTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/LobProbTest.kt new file mode 100644 index 000000000..190da5f4b --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/LobProbTest.kt @@ -0,0 +1,45 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class LobProbTest { + + @Test + fun create() { + val lobProb = + LobProb.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob(TopLogProb.builder().token("token").addByte(0L).logprob(0.0).build()) + .build() + + assertThat(lobProb.token()).isEqualTo("token") + assertThat(lobProb.bytes()).containsExactly(0L) + assertThat(lobProb.logprob()).isEqualTo(0.0) + assertThat(lobProb.topLogprobs()) + .containsExactly(TopLogProb.builder().token("token").addByte(0L).logprob(0.0).build()) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val lobProb = + LobProb.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob(TopLogProb.builder().token("token").addByte(0L).logprob(0.0).build()) + .build() + + val roundtrippedLobProb = + jsonMapper.readValue(jsonMapper.writeValueAsString(lobProb), jacksonTypeRef()) + + assertThat(roundtrippedLobProb).isEqualTo(lobProb) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/MessageTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/MessageTest.kt new file mode 100644 index 000000000..bfeca181f --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/MessageTest.kt @@ -0,0 +1,47 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class MessageTest { + + @Test + fun create() { + val message = + Message.builder() + .id("id") + .addInputTextContent("text") + .role(Message.Role.UNKNOWN) + .status(Message.Status.IN_PROGRESS) + .build() + + assertThat(message.id()).isEqualTo("id") + assertThat(message.content()) + .containsExactly( + Message.Content.ofInputText(InputTextContent.builder().text("text").build()) + ) + assertThat(message.role()).isEqualTo(Message.Role.UNKNOWN) + assertThat(message.status()).isEqualTo(Message.Status.IN_PROGRESS) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val message = + Message.builder() + .id("id") + .addInputTextContent("text") + .role(Message.Role.UNKNOWN) + .status(Message.Status.IN_PROGRESS) + .build() + + val roundtrippedMessage = + jsonMapper.readValue(jsonMapper.writeValueAsString(message), jacksonTypeRef()) + + assertThat(roundtrippedMessage).isEqualTo(message) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/OutputTextContentTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/OutputTextContentTest.kt new file mode 100644 index 000000000..69c094d35 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/OutputTextContentTest.kt @@ -0,0 +1,94 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class OutputTextContentTest { + + @Test + fun create() { + val outputTextContent = + OutputTextContent.builder() + .addAnnotation( + FileCitationBody.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + LobProb.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + TopLogProb.builder().token("token").addByte(0L).logprob(0.0).build() + ) + .build() + ) + .build() + + assertThat(outputTextContent.annotations()) + .containsExactly( + OutputTextContent.Annotation.ofFileCitation( + FileCitationBody.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + ) + assertThat(outputTextContent.text()).isEqualTo("text") + assertThat(outputTextContent.logprobs().getOrNull()) + .containsExactly( + LobProb.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + TopLogProb.builder().token("token").addByte(0L).logprob(0.0).build() + ) + .build() + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val outputTextContent = + OutputTextContent.builder() + .addAnnotation( + FileCitationBody.builder() + .fileId("file_id") + .filename("filename") + .index(0L) + .build() + ) + .text("text") + .addLogprob( + LobProb.builder() + .token("token") + .addByte(0L) + .logprob(0.0) + .addTopLogprob( + TopLogProb.builder().token("token").addByte(0L).logprob(0.0).build() + ) + .build() + ) + .build() + + val roundtrippedOutputTextContent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(outputTextContent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedOutputTextContent).isEqualTo(outputTextContent) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/RefusalContentTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/RefusalContentTest.kt new file mode 100644 index 000000000..b5407f4a1 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/RefusalContentTest.kt @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class RefusalContentTest { + + @Test + fun create() { + val refusalContent = RefusalContent.builder().refusal("refusal").build() + + assertThat(refusalContent.refusal()).isEqualTo("refusal") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val refusalContent = RefusalContent.builder().refusal("refusal").build() + + val roundtrippedRefusalContent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(refusalContent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedRefusalContent).isEqualTo(refusalContent) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/SummaryTextContentTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/SummaryTextContentTest.kt new file mode 100644 index 000000000..c4bcd3cc7 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/SummaryTextContentTest.kt @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SummaryTextContentTest { + + @Test + fun create() { + val summaryTextContent = SummaryTextContent.builder().text("text").build() + + assertThat(summaryTextContent.text()).isEqualTo("text") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val summaryTextContent = SummaryTextContent.builder().text("text").build() + + val roundtrippedSummaryTextContent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(summaryTextContent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedSummaryTextContent).isEqualTo(summaryTextContent) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/TextContentTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/TextContentTest.kt new file mode 100644 index 000000000..67b008293 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/TextContentTest.kt @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TextContentTest { + + @Test + fun create() { + val textContent = TextContent.builder().text("text").build() + + assertThat(textContent.text()).isEqualTo("text") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val textContent = TextContent.builder().text("text").build() + + val roundtrippedTextContent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(textContent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedTextContent).isEqualTo(textContent) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/TopLogProbTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/TopLogProbTest.kt new file mode 100644 index 000000000..01fb32b4d --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/TopLogProbTest.kt @@ -0,0 +1,34 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TopLogProbTest { + + @Test + fun create() { + val topLogProb = TopLogProb.builder().token("token").addByte(0L).logprob(0.0).build() + + assertThat(topLogProb.token()).isEqualTo("token") + assertThat(topLogProb.bytes()).containsExactly(0L) + assertThat(topLogProb.logprob()).isEqualTo(0.0) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val topLogProb = TopLogProb.builder().token("token").addByte(0L).logprob(0.0).build() + + val roundtrippedTopLogProb = + jsonMapper.readValue( + jsonMapper.writeValueAsString(topLogProb), + jacksonTypeRef(), + ) + + assertThat(roundtrippedTopLogProb).isEqualTo(topLogProb) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/UrlCitationBodyTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/UrlCitationBodyTest.kt new file mode 100644 index 000000000..6d7a1a26e --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/UrlCitationBodyTest.kt @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UrlCitationBodyTest { + + @Test + fun create() { + val urlCitationBody = + UrlCitationBody.builder().endIndex(0L).startIndex(0L).title("title").url("url").build() + + assertThat(urlCitationBody.endIndex()).isEqualTo(0L) + assertThat(urlCitationBody.startIndex()).isEqualTo(0L) + assertThat(urlCitationBody.title()).isEqualTo("title") + assertThat(urlCitationBody.url()).isEqualTo("url") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val urlCitationBody = + UrlCitationBody.builder().endIndex(0L).startIndex(0L).title("title").url("url").build() + + val roundtrippedUrlCitationBody = + jsonMapper.readValue( + jsonMapper.writeValueAsString(urlCitationBody), + jacksonTypeRef(), + ) + + assertThat(roundtrippedUrlCitationBody).isEqualTo(urlCitationBody) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ConversationItemListTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ConversationItemListTest.kt new file mode 100644 index 000000000..59b6bcc23 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ConversationItemListTest.kt @@ -0,0 +1,72 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import com.openai.models.conversations.Message +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ConversationItemListTest { + + @Test + fun create() { + val conversationItemList = + ConversationItemList.builder() + .addData( + Message.builder() + .id("id") + .addInputTextContent("text") + .role(Message.Role.UNKNOWN) + .status(Message.Status.IN_PROGRESS) + .build() + ) + .firstId("first_id") + .hasMore(true) + .lastId("last_id") + .build() + + assertThat(conversationItemList.data()) + .containsExactly( + ConversationItem.ofMessage( + Message.builder() + .id("id") + .addInputTextContent("text") + .role(Message.Role.UNKNOWN) + .status(Message.Status.IN_PROGRESS) + .build() + ) + ) + assertThat(conversationItemList.firstId()).isEqualTo("first_id") + assertThat(conversationItemList.hasMore()).isEqualTo(true) + assertThat(conversationItemList.lastId()).isEqualTo("last_id") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val conversationItemList = + ConversationItemList.builder() + .addData( + Message.builder() + .id("id") + .addInputTextContent("text") + .role(Message.Role.UNKNOWN) + .status(Message.Status.IN_PROGRESS) + .build() + ) + .firstId("first_id") + .hasMore(true) + .lastId("last_id") + .build() + + val roundtrippedConversationItemList = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItemList), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItemList).isEqualTo(conversationItemList) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ConversationItemTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ConversationItemTest.kt new file mode 100644 index 000000000..02f6ec3c1 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ConversationItemTest.kt @@ -0,0 +1,1135 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +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.conversations.Message +import com.openai.models.responses.ResponseCodeInterpreterToolCall +import com.openai.models.responses.ResponseComputerToolCall +import com.openai.models.responses.ResponseComputerToolCallOutputItem +import com.openai.models.responses.ResponseComputerToolCallOutputScreenshot +import com.openai.models.responses.ResponseCustomToolCall +import com.openai.models.responses.ResponseCustomToolCallOutput +import com.openai.models.responses.ResponseFileSearchToolCall +import com.openai.models.responses.ResponseFunctionToolCall +import com.openai.models.responses.ResponseFunctionToolCallItem +import com.openai.models.responses.ResponseFunctionToolCallOutputItem +import com.openai.models.responses.ResponseFunctionWebSearch +import com.openai.models.responses.ResponseReasoningItem +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 ConversationItemTest { + + @Test + fun ofMessage() { + val message = + Message.builder() + .id("id") + .addInputTextContent("text") + .role(Message.Role.UNKNOWN) + .status(Message.Status.IN_PROGRESS) + .build() + + val conversationItem = ConversationItem.ofMessage(message) + + assertThat(conversationItem.message()).contains(message) + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofMessageRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofMessage( + Message.builder() + .id("id") + .addInputTextContent("text") + .role(Message.Role.UNKNOWN) + .status(Message.Status.IN_PROGRESS) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofFunctionCall() { + val functionCall = + ResponseFunctionToolCallItem.builder() + .arguments("arguments") + .callId("call_id") + .name("name") + .id("id") + .status(ResponseFunctionToolCall.Status.IN_PROGRESS) + .build() + + val conversationItem = ConversationItem.ofFunctionCall(functionCall) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).contains(functionCall) + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofFunctionCallRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofFunctionCall( + ResponseFunctionToolCallItem.builder() + .arguments("arguments") + .callId("call_id") + .name("name") + .id("id") + .status(ResponseFunctionToolCall.Status.IN_PROGRESS) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofFunctionCallOutput() { + val functionCallOutput = + ResponseFunctionToolCallOutputItem.builder() + .id("id") + .callId("call_id") + .output("output") + .status(ResponseFunctionToolCallOutputItem.Status.IN_PROGRESS) + .build() + + val conversationItem = ConversationItem.ofFunctionCallOutput(functionCallOutput) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).contains(functionCallOutput) + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofFunctionCallOutputRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofFunctionCallOutput( + ResponseFunctionToolCallOutputItem.builder() + .id("id") + .callId("call_id") + .output("output") + .status(ResponseFunctionToolCallOutputItem.Status.IN_PROGRESS) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofFileSearchCall() { + val fileSearchCall = + ResponseFileSearchToolCall.builder() + .id("id") + .addQuery("string") + .status(ResponseFileSearchToolCall.Status.IN_PROGRESS) + .addResult( + ResponseFileSearchToolCall.Result.builder() + .attributes( + ResponseFileSearchToolCall.Result.Attributes.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .fileId("file_id") + .filename("filename") + .score(0.0f) + .text("text") + .build() + ) + .build() + + val conversationItem = ConversationItem.ofFileSearchCall(fileSearchCall) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).contains(fileSearchCall) + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofFileSearchCallRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofFileSearchCall( + ResponseFileSearchToolCall.builder() + .id("id") + .addQuery("string") + .status(ResponseFileSearchToolCall.Status.IN_PROGRESS) + .addResult( + ResponseFileSearchToolCall.Result.builder() + .attributes( + ResponseFileSearchToolCall.Result.Attributes.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .fileId("file_id") + .filename("filename") + .score(0.0f) + .text("text") + .build() + ) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofWebSearchCall() { + val webSearchCall = + ResponseFunctionWebSearch.builder() + .id("id") + .searchAction("query") + .status(ResponseFunctionWebSearch.Status.IN_PROGRESS) + .build() + + val conversationItem = ConversationItem.ofWebSearchCall(webSearchCall) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).contains(webSearchCall) + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofWebSearchCallRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofWebSearchCall( + ResponseFunctionWebSearch.builder() + .id("id") + .searchAction("query") + .status(ResponseFunctionWebSearch.Status.IN_PROGRESS) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofImageGenerationCall() { + val imageGenerationCall = + ConversationItem.ImageGenerationCall.builder() + .id("id") + .result("result") + .status(ConversationItem.ImageGenerationCall.Status.IN_PROGRESS) + .build() + + val conversationItem = ConversationItem.ofImageGenerationCall(imageGenerationCall) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).contains(imageGenerationCall) + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofImageGenerationCallRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofImageGenerationCall( + ConversationItem.ImageGenerationCall.builder() + .id("id") + .result("result") + .status(ConversationItem.ImageGenerationCall.Status.IN_PROGRESS) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofComputerCall() { + val computerCall = + ResponseComputerToolCall.builder() + .id("id") + .action( + ResponseComputerToolCall.Action.Click.builder() + .button(ResponseComputerToolCall.Action.Click.Button.LEFT) + .x(0L) + .y(0L) + .build() + ) + .callId("call_id") + .addPendingSafetyCheck( + ResponseComputerToolCall.PendingSafetyCheck.builder() + .id("id") + .code("code") + .message("message") + .build() + ) + .status(ResponseComputerToolCall.Status.IN_PROGRESS) + .type(ResponseComputerToolCall.Type.COMPUTER_CALL) + .build() + + val conversationItem = ConversationItem.ofComputerCall(computerCall) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).contains(computerCall) + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofComputerCallRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofComputerCall( + ResponseComputerToolCall.builder() + .id("id") + .action( + ResponseComputerToolCall.Action.Click.builder() + .button(ResponseComputerToolCall.Action.Click.Button.LEFT) + .x(0L) + .y(0L) + .build() + ) + .callId("call_id") + .addPendingSafetyCheck( + ResponseComputerToolCall.PendingSafetyCheck.builder() + .id("id") + .code("code") + .message("message") + .build() + ) + .status(ResponseComputerToolCall.Status.IN_PROGRESS) + .type(ResponseComputerToolCall.Type.COMPUTER_CALL) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofComputerCallOutput() { + val computerCallOutput = + ResponseComputerToolCallOutputItem.builder() + .id("id") + .callId("call_id") + .output( + ResponseComputerToolCallOutputScreenshot.builder() + .fileId("file_id") + .imageUrl("image_url") + .build() + ) + .addAcknowledgedSafetyCheck( + ResponseComputerToolCallOutputItem.AcknowledgedSafetyCheck.builder() + .id("id") + .code("code") + .message("message") + .build() + ) + .status(ResponseComputerToolCallOutputItem.Status.IN_PROGRESS) + .build() + + val conversationItem = ConversationItem.ofComputerCallOutput(computerCallOutput) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).contains(computerCallOutput) + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofComputerCallOutputRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofComputerCallOutput( + ResponseComputerToolCallOutputItem.builder() + .id("id") + .callId("call_id") + .output( + ResponseComputerToolCallOutputScreenshot.builder() + .fileId("file_id") + .imageUrl("image_url") + .build() + ) + .addAcknowledgedSafetyCheck( + ResponseComputerToolCallOutputItem.AcknowledgedSafetyCheck.builder() + .id("id") + .code("code") + .message("message") + .build() + ) + .status(ResponseComputerToolCallOutputItem.Status.IN_PROGRESS) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofReasoning() { + val reasoning = + ResponseReasoningItem.builder() + .id("id") + .addSummary(ResponseReasoningItem.Summary.builder().text("text").build()) + .addContent(ResponseReasoningItem.Content.builder().text("text").build()) + .encryptedContent("encrypted_content") + .status(ResponseReasoningItem.Status.IN_PROGRESS) + .build() + + val conversationItem = ConversationItem.ofReasoning(reasoning) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).contains(reasoning) + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofReasoningRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofReasoning( + ResponseReasoningItem.builder() + .id("id") + .addSummary(ResponseReasoningItem.Summary.builder().text("text").build()) + .addContent(ResponseReasoningItem.Content.builder().text("text").build()) + .encryptedContent("encrypted_content") + .status(ResponseReasoningItem.Status.IN_PROGRESS) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofCodeInterpreterCall() { + val codeInterpreterCall = + ResponseCodeInterpreterToolCall.builder() + .id("id") + .code("code") + .containerId("container_id") + .addLogsOutput("logs") + .status(ResponseCodeInterpreterToolCall.Status.IN_PROGRESS) + .build() + + val conversationItem = ConversationItem.ofCodeInterpreterCall(codeInterpreterCall) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).contains(codeInterpreterCall) + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofCodeInterpreterCallRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofCodeInterpreterCall( + ResponseCodeInterpreterToolCall.builder() + .id("id") + .code("code") + .containerId("container_id") + .addLogsOutput("logs") + .status(ResponseCodeInterpreterToolCall.Status.IN_PROGRESS) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofLocalShellCall() { + val localShellCall = + ConversationItem.LocalShellCall.builder() + .id("id") + .action( + ConversationItem.LocalShellCall.Action.builder() + .addCommand("string") + .env( + ConversationItem.LocalShellCall.Action.Env.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .timeoutMs(0L) + .user("user") + .workingDirectory("working_directory") + .build() + ) + .callId("call_id") + .status(ConversationItem.LocalShellCall.Status.IN_PROGRESS) + .build() + + val conversationItem = ConversationItem.ofLocalShellCall(localShellCall) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).contains(localShellCall) + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofLocalShellCallRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofLocalShellCall( + ConversationItem.LocalShellCall.builder() + .id("id") + .action( + ConversationItem.LocalShellCall.Action.builder() + .addCommand("string") + .env( + ConversationItem.LocalShellCall.Action.Env.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .timeoutMs(0L) + .user("user") + .workingDirectory("working_directory") + .build() + ) + .callId("call_id") + .status(ConversationItem.LocalShellCall.Status.IN_PROGRESS) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofLocalShellCallOutput() { + val localShellCallOutput = + ConversationItem.LocalShellCallOutput.builder() + .id("id") + .output("output") + .status(ConversationItem.LocalShellCallOutput.Status.IN_PROGRESS) + .build() + + val conversationItem = ConversationItem.ofLocalShellCallOutput(localShellCallOutput) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).contains(localShellCallOutput) + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofLocalShellCallOutputRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofLocalShellCallOutput( + ConversationItem.LocalShellCallOutput.builder() + .id("id") + .output("output") + .status(ConversationItem.LocalShellCallOutput.Status.IN_PROGRESS) + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofMcpListTools() { + val mcpListTools = + ConversationItem.McpListTools.builder() + .id("id") + .serverLabel("server_label") + .addTool( + ConversationItem.McpListTools.Tool.builder() + .inputSchema(JsonValue.from(mapOf())) + .name("name") + .annotations(JsonValue.from(mapOf())) + .description("description") + .build() + ) + .error("error") + .build() + + val conversationItem = ConversationItem.ofMcpListTools(mcpListTools) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).contains(mcpListTools) + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofMcpListToolsRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofMcpListTools( + ConversationItem.McpListTools.builder() + .id("id") + .serverLabel("server_label") + .addTool( + ConversationItem.McpListTools.Tool.builder() + .inputSchema(JsonValue.from(mapOf())) + .name("name") + .annotations(JsonValue.from(mapOf())) + .description("description") + .build() + ) + .error("error") + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofMcpApprovalRequest() { + val mcpApprovalRequest = + ConversationItem.McpApprovalRequest.builder() + .id("id") + .arguments("arguments") + .name("name") + .serverLabel("server_label") + .build() + + val conversationItem = ConversationItem.ofMcpApprovalRequest(mcpApprovalRequest) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).contains(mcpApprovalRequest) + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofMcpApprovalRequestRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofMcpApprovalRequest( + ConversationItem.McpApprovalRequest.builder() + .id("id") + .arguments("arguments") + .name("name") + .serverLabel("server_label") + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofMcpApprovalResponse() { + val mcpApprovalResponse = + ConversationItem.McpApprovalResponse.builder() + .id("id") + .approvalRequestId("approval_request_id") + .approve(true) + .reason("reason") + .build() + + val conversationItem = ConversationItem.ofMcpApprovalResponse(mcpApprovalResponse) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).contains(mcpApprovalResponse) + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofMcpApprovalResponseRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofMcpApprovalResponse( + ConversationItem.McpApprovalResponse.builder() + .id("id") + .approvalRequestId("approval_request_id") + .approve(true) + .reason("reason") + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofMcpCall() { + val mcpCall = + ConversationItem.McpCall.builder() + .id("id") + .arguments("arguments") + .name("name") + .serverLabel("server_label") + .error("error") + .output("output") + .build() + + val conversationItem = ConversationItem.ofMcpCall(mcpCall) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).contains(mcpCall) + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofMcpCallRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofMcpCall( + ConversationItem.McpCall.builder() + .id("id") + .arguments("arguments") + .name("name") + .serverLabel("server_label") + .error("error") + .output("output") + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofCustomToolCall() { + val customToolCall = + ResponseCustomToolCall.builder() + .callId("call_id") + .input("input") + .name("name") + .id("id") + .build() + + val conversationItem = ConversationItem.ofCustomToolCall(customToolCall) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).contains(customToolCall) + assertThat(conversationItem.customToolCallOutput()).isEmpty + } + + @Test + fun ofCustomToolCallRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofCustomToolCall( + ResponseCustomToolCall.builder() + .callId("call_id") + .input("input") + .name("name") + .id("id") + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + @Test + fun ofCustomToolCallOutput() { + val customToolCallOutput = + ResponseCustomToolCallOutput.builder() + .callId("call_id") + .output("output") + .id("id") + .build() + + val conversationItem = ConversationItem.ofCustomToolCallOutput(customToolCallOutput) + + assertThat(conversationItem.message()).isEmpty + assertThat(conversationItem.functionCall()).isEmpty + assertThat(conversationItem.functionCallOutput()).isEmpty + assertThat(conversationItem.fileSearchCall()).isEmpty + assertThat(conversationItem.webSearchCall()).isEmpty + assertThat(conversationItem.imageGenerationCall()).isEmpty + assertThat(conversationItem.computerCall()).isEmpty + assertThat(conversationItem.computerCallOutput()).isEmpty + assertThat(conversationItem.reasoning()).isEmpty + assertThat(conversationItem.codeInterpreterCall()).isEmpty + assertThat(conversationItem.localShellCall()).isEmpty + assertThat(conversationItem.localShellCallOutput()).isEmpty + assertThat(conversationItem.mcpListTools()).isEmpty + assertThat(conversationItem.mcpApprovalRequest()).isEmpty + assertThat(conversationItem.mcpApprovalResponse()).isEmpty + assertThat(conversationItem.mcpCall()).isEmpty + assertThat(conversationItem.customToolCall()).isEmpty + assertThat(conversationItem.customToolCallOutput()).contains(customToolCallOutput) + } + + @Test + fun ofCustomToolCallOutputRoundtrip() { + val jsonMapper = jsonMapper() + val conversationItem = + ConversationItem.ofCustomToolCallOutput( + ResponseCustomToolCallOutput.builder() + .callId("call_id") + .output("output") + .id("id") + .build() + ) + + val roundtrippedConversationItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(conversationItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedConversationItem).isEqualTo(conversationItem) + } + + 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 conversationItem = + jsonMapper().convertValue(testCase.value, jacksonTypeRef()) + + val e = assertThrows { conversationItem.validate() } + assertThat(e).hasMessageStartingWith("Unknown ") + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemCreateParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemCreateParamsTest.kt new file mode 100644 index 000000000..760c09143 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemCreateParamsTest.kt @@ -0,0 +1,142 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +import com.openai.core.http.QueryParams +import com.openai.models.responses.EasyInputMessage +import com.openai.models.responses.ResponseIncludable +import com.openai.models.responses.ResponseInputItem +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ItemCreateParamsTest { + + @Test + fun create() { + ItemCreateParams.builder() + .conversationId("conv_123") + .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .type(EasyInputMessage.Type.MESSAGE) + .build() + ) + .build() + } + + @Test + fun pathParams() { + val params = + ItemCreateParams.builder() + .conversationId("conv_123") + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .build() + ) + .build() + + assertThat(params._pathParam(0)).isEqualTo("conv_123") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = + ItemCreateParams.builder() + .conversationId("conv_123") + .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .type(EasyInputMessage.Type.MESSAGE) + .build() + ) + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder().put("include[]", "code_interpreter_call.outputs").build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = + ItemCreateParams.builder() + .conversationId("conv_123") + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .build() + ) + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } + + @Test + fun body() { + val params = + ItemCreateParams.builder() + .conversationId("conv_123") + .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .type(EasyInputMessage.Type.MESSAGE) + .build() + ) + .build() + + val body = params._body() + + assertThat(body.items()) + .containsExactly( + ResponseInputItem.ofEasyInputMessage( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .type(EasyInputMessage.Type.MESSAGE) + .build() + ) + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + ItemCreateParams.builder() + .conversationId("conv_123") + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .build() + ) + .build() + + val body = params._body() + + assertThat(body.items()) + .containsExactly( + ResponseInputItem.ofEasyInputMessage( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .build() + ) + ) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemDeleteParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemDeleteParamsTest.kt new file mode 100644 index 000000000..28deac02a --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemDeleteParamsTest.kt @@ -0,0 +1,24 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ItemDeleteParamsTest { + + @Test + fun create() { + ItemDeleteParams.builder().conversationId("conv_123").itemId("msg_abc").build() + } + + @Test + fun pathParams() { + val params = ItemDeleteParams.builder().conversationId("conv_123").itemId("msg_abc").build() + + assertThat(params._pathParam(0)).isEqualTo("conv_123") + assertThat(params._pathParam(1)).isEqualTo("msg_abc") + // out-of-bound path param + assertThat(params._pathParam(2)).isEqualTo("") + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemListParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemListParamsTest.kt new file mode 100644 index 000000000..ae391f377 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemListParamsTest.kt @@ -0,0 +1,64 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +import com.openai.core.http.QueryParams +import com.openai.models.responses.ResponseIncludable +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ItemListParamsTest { + + @Test + fun create() { + ItemListParams.builder() + .conversationId("conv_123") + .after("after") + .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) + .limit(0L) + .order(ItemListParams.Order.ASC) + .build() + } + + @Test + fun pathParams() { + val params = ItemListParams.builder().conversationId("conv_123").build() + + assertThat(params._pathParam(0)).isEqualTo("conv_123") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = + ItemListParams.builder() + .conversationId("conv_123") + .after("after") + .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) + .limit(0L) + .order(ItemListParams.Order.ASC) + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder() + .put("after", "after") + .put("include[]", "code_interpreter_call.outputs") + .put("limit", "0") + .put("order", "asc") + .build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = ItemListParams.builder().conversationId("conv_123").build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemRetrieveParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemRetrieveParamsTest.kt new file mode 100644 index 000000000..fb9fa9419 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/conversations/items/ItemRetrieveParamsTest.kt @@ -0,0 +1,58 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.conversations.items + +import com.openai.core.http.QueryParams +import com.openai.models.responses.ResponseIncludable +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ItemRetrieveParamsTest { + + @Test + fun create() { + ItemRetrieveParams.builder() + .conversationId("conv_123") + .itemId("msg_abc") + .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) + .build() + } + + @Test + fun pathParams() { + val params = + ItemRetrieveParams.builder().conversationId("conv_123").itemId("msg_abc").build() + + assertThat(params._pathParam(0)).isEqualTo("conv_123") + assertThat(params._pathParam(1)).isEqualTo("msg_abc") + // out-of-bound path param + assertThat(params._pathParam(2)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = + ItemRetrieveParams.builder() + .conversationId("conv_123") + .itemId("msg_abc") + .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder().put("include[]", "code_interpreter_call.outputs").build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = + ItemRetrieveParams.builder().conversationId("conv_123").itemId("msg_abc").build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCompletedEventTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCompletedEventTest.kt index d30cc8ab1..09f60ba4f 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCompletedEventTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCompletedEventTest.kt @@ -89,6 +89,7 @@ internal class ResponseCompletedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -217,6 +218,7 @@ internal class ResponseCompletedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -347,6 +349,7 @@ internal class ResponseCompletedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseConversationParamTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseConversationParamTest.kt new file mode 100644 index 000000000..7d5f69c65 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseConversationParamTest.kt @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.models.responses + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ResponseConversationParamTest { + + @Test + fun create() { + val responseConversationParam = ResponseConversationParam.builder().id("id").build() + + assertThat(responseConversationParam.id()).isEqualTo("id") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val responseConversationParam = ResponseConversationParam.builder().id("id").build() + + val roundtrippedResponseConversationParam = + jsonMapper.readValue( + jsonMapper.writeValueAsString(responseConversationParam), + jacksonTypeRef(), + ) + + assertThat(roundtrippedResponseConversationParam).isEqualTo(responseConversationParam) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreateParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreateParamsTest.kt index 84a00ee57..3c85aeba5 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreateParamsTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreateParamsTest.kt @@ -18,6 +18,7 @@ internal class ResponseCreateParamsTest { fun create() { ResponseCreateParams.builder() .background(true) + .conversation("string") .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) .input("string") .instructions("instructions") @@ -88,6 +89,7 @@ internal class ResponseCreateParamsTest { val params = ResponseCreateParams.builder() .background(true) + .conversation("string") .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) .input("string") .instructions("instructions") @@ -155,6 +157,7 @@ internal class ResponseCreateParamsTest { val body = params._body() assertThat(body.background()).contains(true) + assertThat(body.conversation()).contains(ResponseCreateParams.Conversation.ofId("string")) assertThat(body.include().getOrNull()) .containsExactly(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) assertThat(body.input()).contains(ResponseCreateParams.Input.ofText("string")) diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreatedEventTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreatedEventTest.kt index feba1f9c2..8c3d8a36c 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreatedEventTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseCreatedEventTest.kt @@ -89,6 +89,7 @@ internal class ResponseCreatedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -217,6 +218,7 @@ internal class ResponseCreatedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -347,6 +349,7 @@ internal class ResponseCreatedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseFailedEventTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseFailedEventTest.kt index 168ff10d6..520701465 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseFailedEventTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseFailedEventTest.kt @@ -89,6 +89,7 @@ internal class ResponseFailedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -217,6 +218,7 @@ internal class ResponseFailedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -347,6 +349,7 @@ internal class ResponseFailedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseInProgressEventTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseInProgressEventTest.kt index b10eea2e6..bdaac4313 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseInProgressEventTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseInProgressEventTest.kt @@ -89,6 +89,7 @@ internal class ResponseInProgressEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -217,6 +218,7 @@ internal class ResponseInProgressEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -347,6 +349,7 @@ internal class ResponseInProgressEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseIncompleteEventTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseIncompleteEventTest.kt index 2854b607b..ce16b8b7e 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseIncompleteEventTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseIncompleteEventTest.kt @@ -89,6 +89,7 @@ internal class ResponseIncompleteEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -217,6 +218,7 @@ internal class ResponseIncompleteEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -347,6 +349,7 @@ internal class ResponseIncompleteEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseQueuedEventTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseQueuedEventTest.kt index 5d6538791..927392e6a 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseQueuedEventTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseQueuedEventTest.kt @@ -89,6 +89,7 @@ internal class ResponseQueuedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -217,6 +218,7 @@ internal class ResponseQueuedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -347,6 +349,7 @@ internal class ResponseQueuedEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseStreamEventTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseStreamEventTest.kt index feec1a45d..a6cd270f4 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseStreamEventTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseStreamEventTest.kt @@ -859,6 +859,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -1050,6 +1051,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -1473,6 +1475,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -1664,6 +1667,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -2341,6 +2345,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -2532,6 +2537,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -2673,6 +2679,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -2864,6 +2871,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -3005,6 +3013,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -3196,6 +3205,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -6023,6 +6033,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -6214,6 +6225,7 @@ internal class ResponseStreamEventTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseTest.kt index e52b6b5c5..dba13d8b2 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseTest.kt @@ -88,6 +88,7 @@ internal class ResponseTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") @@ -216,6 +217,8 @@ internal class ResponseTest { ) assertThat(response.topP()).contains(1.0) assertThat(response.background()).contains(true) + assertThat(response.conversation()) + .contains(Response.Conversation.builder().id("id").build()) assertThat(response.maxOutputTokens()).contains(0L) assertThat(response.maxToolCalls()).contains(0L) assertThat(response.previousResponseId()).contains("previous_response_id") @@ -343,6 +346,7 @@ internal class ResponseTest { ) .topP(1.0) .background(true) + .conversation(Response.Conversation.builder().id("id").build()) .maxOutputTokens(0L) .maxToolCalls(0L) .previousResponseId("previous_response_id") diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseCreateParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseCreateParamsTest.kt index 9542f6835..e9a69b8d4 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseCreateParamsTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseCreateParamsTest.kt @@ -60,6 +60,9 @@ internal class StructuredResponseCreateParamsTest { private val SERVICE_TIER = ResponseCreateParams.ServiceTier.AUTO private val REASONING = Reasoning.builder().build() private val PROMPT = ResponsePrompt.builder().id("test-prompt-id").build() + private val RESPONSE_CONVERSATION_PARAM = + ResponseConversationParam.builder().id(STRING).build() + private val CONVERSATION = ResponseCreateParams.Conversation.ofId(STRING) private val TOOL_CHOICE_TYPE = ToolChoiceTypes.Type.FILE_SEARCH private val TOOL_CHOICE_TYPES = ToolChoiceTypes.builder().type(TOOL_CHOICE_TYPE).build() @@ -120,6 +123,11 @@ internal class StructuredResponseCreateParamsTest { DelegationWriteTestCase("background", BOOLEAN), DelegationWriteTestCase("background", OPTIONAL), DelegationWriteTestCase("background", JSON_FIELD), + DelegationWriteTestCase("conversation", CONVERSATION), + DelegationWriteTestCase("conversation", OPTIONAL), + DelegationWriteTestCase("conversation", JSON_FIELD), + DelegationWriteTestCase("conversation", STRING), + DelegationWriteTestCase("conversation", RESPONSE_CONVERSATION_PARAM), DelegationWriteTestCase("include", LIST), DelegationWriteTestCase("include", OPTIONAL), DelegationWriteTestCase("include", JSON_FIELD), @@ -188,6 +196,7 @@ internal class StructuredResponseCreateParamsTest { DelegationWriteTestCase("addTool", WEB_SEARCH_TOOL), DelegationWriteTestCase("addTool", COMPUTER_TOOL), DelegationWriteTestCase("addTool", MCP_TOOL), + DelegationWriteTestCase("addMcpTool", STRING), DelegationWriteTestCase("addTool", CODE_INTERPRETER_TOOL), DelegationWriteTestCase("addCodeInterpreterTool", CODE_INTERPRETER_CONTAINER), DelegationWriteTestCase("addCodeInterpreterTool", STRING), diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseTest.kt index e41335b2a..de6c6f2dc 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseTest.kt @@ -112,6 +112,8 @@ internal class StructuredResponseTest { DelegationReadTestCase("_user", JSON_FIELD), DelegationReadTestCase("background", OPTIONAL), DelegationReadTestCase("_background", JSON_FIELD), + DelegationReadTestCase("conversation", OPTIONAL), + DelegationReadTestCase("_conversation", JSON_FIELD), DelegationReadTestCase("_additionalProperties", MAP), // `validate()` and `isValid()` (which calls `validate()`) are tested separately, // as they require special handling. diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ToolTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ToolTest.kt index ecc0576c4..f66eaa777 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ToolTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ToolTest.kt @@ -228,8 +228,9 @@ internal class ToolTest { val mcp = Tool.Mcp.builder() .serverLabel("server_label") - .serverUrl("server_url") .allowedToolsOfMcp(listOf("string")) + .authorization("authorization") + .connectorId(Tool.Mcp.ConnectorId.CONNECTOR_DROPBOX) .headers( Tool.Mcp.Headers.builder() .putAdditionalProperty("foo", JsonValue.from("string")) @@ -239,17 +240,20 @@ internal class ToolTest { Tool.Mcp.RequireApproval.McpToolApprovalFilter.builder() .always( Tool.Mcp.RequireApproval.McpToolApprovalFilter.Always.builder() + .readOnly(true) .addToolName("string") .build() ) .never( Tool.Mcp.RequireApproval.McpToolApprovalFilter.Never.builder() + .readOnly(true) .addToolName("string") .build() ) .build() ) .serverDescription("server_description") + .serverUrl("server_url") .build() val tool = Tool.ofMcp(mcp) @@ -272,8 +276,9 @@ internal class ToolTest { Tool.ofMcp( Tool.Mcp.builder() .serverLabel("server_label") - .serverUrl("server_url") .allowedToolsOfMcp(listOf("string")) + .authorization("authorization") + .connectorId(Tool.Mcp.ConnectorId.CONNECTOR_DROPBOX) .headers( Tool.Mcp.Headers.builder() .putAdditionalProperty("foo", JsonValue.from("string")) @@ -283,17 +288,20 @@ internal class ToolTest { Tool.Mcp.RequireApproval.McpToolApprovalFilter.builder() .always( Tool.Mcp.RequireApproval.McpToolApprovalFilter.Always.builder() + .readOnly(true) .addToolName("string") .build() ) .never( Tool.Mcp.RequireApproval.McpToolApprovalFilter.Never.builder() + .readOnly(true) .addToolName("string") .build() ) .build() ) .serverDescription("server_description") + .serverUrl("server_url") .build() ) diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/inputitems/InputItemListParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/inputitems/InputItemListParamsTest.kt index ca022c0e1..a67a04f09 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/inputitems/InputItemListParamsTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/inputitems/InputItemListParamsTest.kt @@ -14,7 +14,6 @@ internal class InputItemListParamsTest { InputItemListParams.builder() .responseId("response_id") .after("after") - .before("before") .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) .limit(0L) .order(InputItemListParams.Order.ASC) @@ -36,7 +35,6 @@ internal class InputItemListParamsTest { InputItemListParams.builder() .responseId("response_id") .after("after") - .before("before") .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) .limit(0L) .order(InputItemListParams.Order.ASC) @@ -48,7 +46,6 @@ internal class InputItemListParamsTest { .isEqualTo( QueryParams.builder() .put("after", "after") - .put("before", "before") .put("include[]", "code_interpreter_call.outputs") .put("limit", "0") .put("order", "asc") diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/ConversationServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/ConversationServiceAsyncTest.kt new file mode 100644 index 000000000..5ab198615 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/ConversationServiceAsyncTest.kt @@ -0,0 +1,102 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.async + +import com.openai.TestServerExtension +import com.openai.client.okhttp.OpenAIOkHttpClientAsync +import com.openai.core.JsonValue +import com.openai.models.conversations.ConversationCreateParams +import com.openai.models.conversations.ConversationUpdateParams +import com.openai.models.responses.EasyInputMessage +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class ConversationServiceAsyncTest { + + @Test + fun create() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val conversationServiceAsync = client.conversations() + + val conversationFuture = + conversationServiceAsync.create( + ConversationCreateParams.builder() + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .type(EasyInputMessage.Type.MESSAGE) + .build() + ) + .metadata( + ConversationCreateParams.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .build() + ) + + val conversation = conversationFuture.get() + conversation.validate() + } + + @Test + fun retrieve() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val conversationServiceAsync = client.conversations() + + val conversationFuture = conversationServiceAsync.retrieve("conv_123") + + val conversation = conversationFuture.get() + conversation.validate() + } + + @Test + fun update() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val conversationServiceAsync = client.conversations() + + val conversationFuture = + conversationServiceAsync.update( + ConversationUpdateParams.builder() + .conversationId("conv_123") + .metadata( + ConversationUpdateParams.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .build() + ) + + val conversation = conversationFuture.get() + conversation.validate() + } + + @Test + fun delete() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val conversationServiceAsync = client.conversations() + + val conversationDeletedResourceFuture = conversationServiceAsync.delete("conv_123") + + val conversationDeletedResource = conversationDeletedResourceFuture.get() + conversationDeletedResource.validate() + } +} 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 b4f2f524e..129791cd6 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 @@ -35,6 +35,7 @@ internal class ResponseServiceAsyncTest { responseServiceAsync.create( ResponseCreateParams.builder() .background(true) + .conversation("string") .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) .input("string") .instructions("instructions") @@ -119,6 +120,7 @@ internal class ResponseServiceAsyncTest { responseServiceAsync.createStreaming( ResponseCreateParams.builder() .background(true) + .conversation("string") .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) .input("string") .instructions("instructions") diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/conversations/ItemServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/conversations/ItemServiceAsyncTest.kt new file mode 100644 index 000000000..7243c0120 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/conversations/ItemServiceAsyncTest.kt @@ -0,0 +1,100 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.async.conversations + +import com.openai.TestServerExtension +import com.openai.client.okhttp.OpenAIOkHttpClientAsync +import com.openai.models.conversations.items.ItemCreateParams +import com.openai.models.conversations.items.ItemDeleteParams +import com.openai.models.conversations.items.ItemRetrieveParams +import com.openai.models.responses.EasyInputMessage +import com.openai.models.responses.ResponseIncludable +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class ItemServiceAsyncTest { + + @Test + fun create() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val itemServiceAsync = client.conversations().items() + + val conversationItemListFuture = + itemServiceAsync.create( + ItemCreateParams.builder() + .conversationId("conv_123") + .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .type(EasyInputMessage.Type.MESSAGE) + .build() + ) + .build() + ) + + val conversationItemList = conversationItemListFuture.get() + conversationItemList.validate() + } + + @Test + fun retrieve() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val itemServiceAsync = client.conversations().items() + + val conversationItemFuture = + itemServiceAsync.retrieve( + ItemRetrieveParams.builder() + .conversationId("conv_123") + .itemId("msg_abc") + .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) + .build() + ) + + val conversationItem = conversationItemFuture.get() + conversationItem.validate() + } + + @Test + fun list() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val itemServiceAsync = client.conversations().items() + + val pageFuture = itemServiceAsync.list("conv_123") + + val page = pageFuture.get() + page.response().validate() + } + + @Test + fun delete() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val itemServiceAsync = client.conversations().items() + + val conversationFuture = + itemServiceAsync.delete( + ItemDeleteParams.builder().conversationId("conv_123").itemId("msg_abc").build() + ) + + val conversation = conversationFuture.get() + conversation.validate() + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/ConversationServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/ConversationServiceTest.kt new file mode 100644 index 000000000..31062c171 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/ConversationServiceTest.kt @@ -0,0 +1,98 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.blocking + +import com.openai.TestServerExtension +import com.openai.client.okhttp.OpenAIOkHttpClient +import com.openai.core.JsonValue +import com.openai.models.conversations.ConversationCreateParams +import com.openai.models.conversations.ConversationUpdateParams +import com.openai.models.responses.EasyInputMessage +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class ConversationServiceTest { + + @Test + fun create() { + val client = + OpenAIOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val conversationService = client.conversations() + + val conversation = + conversationService.create( + ConversationCreateParams.builder() + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .type(EasyInputMessage.Type.MESSAGE) + .build() + ) + .metadata( + ConversationCreateParams.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .build() + ) + + conversation.validate() + } + + @Test + fun retrieve() { + val client = + OpenAIOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val conversationService = client.conversations() + + val conversation = conversationService.retrieve("conv_123") + + conversation.validate() + } + + @Test + fun update() { + val client = + OpenAIOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val conversationService = client.conversations() + + val conversation = + conversationService.update( + ConversationUpdateParams.builder() + .conversationId("conv_123") + .metadata( + ConversationUpdateParams.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .build() + ) + + conversation.validate() + } + + @Test + fun delete() { + val client = + OpenAIOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val conversationService = client.conversations() + + val conversationDeletedResource = conversationService.delete("conv_123") + + conversationDeletedResource.validate() + } +} 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 c4c0f4b45..559c03462 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 @@ -35,6 +35,7 @@ internal class ResponseServiceTest { responseService.create( ResponseCreateParams.builder() .background(true) + .conversation("string") .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) .input("string") .instructions("instructions") @@ -118,6 +119,7 @@ internal class ResponseServiceTest { responseService.createStreaming( ResponseCreateParams.builder() .background(true) + .conversation("string") .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) .input("string") .instructions("instructions") diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/conversations/ItemServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/conversations/ItemServiceTest.kt new file mode 100644 index 000000000..18d2c8d99 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/conversations/ItemServiceTest.kt @@ -0,0 +1,96 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.openai.services.blocking.conversations + +import com.openai.TestServerExtension +import com.openai.client.okhttp.OpenAIOkHttpClient +import com.openai.models.conversations.items.ItemCreateParams +import com.openai.models.conversations.items.ItemDeleteParams +import com.openai.models.conversations.items.ItemRetrieveParams +import com.openai.models.responses.EasyInputMessage +import com.openai.models.responses.ResponseIncludable +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class ItemServiceTest { + + @Test + fun create() { + val client = + OpenAIOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val itemService = client.conversations().items() + + val conversationItemList = + itemService.create( + ItemCreateParams.builder() + .conversationId("conv_123") + .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) + .addItem( + EasyInputMessage.builder() + .content("string") + .role(EasyInputMessage.Role.USER) + .type(EasyInputMessage.Type.MESSAGE) + .build() + ) + .build() + ) + + conversationItemList.validate() + } + + @Test + fun retrieve() { + val client = + OpenAIOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val itemService = client.conversations().items() + + val conversationItem = + itemService.retrieve( + ItemRetrieveParams.builder() + .conversationId("conv_123") + .itemId("msg_abc") + .addInclude(ResponseIncludable.CODE_INTERPRETER_CALL_OUTPUTS) + .build() + ) + + conversationItem.validate() + } + + @Test + fun list() { + val client = + OpenAIOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val itemService = client.conversations().items() + + val page = itemService.list("conv_123") + + page.response().validate() + } + + @Test + fun delete() { + val client = + OpenAIOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val itemService = client.conversations().items() + + val conversation = + itemService.delete( + ItemDeleteParams.builder().conversationId("conv_123").itemId("msg_abc").build() + ) + + conversation.validate() + } +} diff --git a/openai-java-proguard-test/build.gradle.kts b/openai-java-proguard-test/build.gradle.kts index de73d5f7b..c7a211fed 100644 --- a/openai-java-proguard-test/build.gradle.kts +++ b/openai-java-proguard-test/build.gradle.kts @@ -37,8 +37,6 @@ val proguardJar by tasks.registering(proguard.gradle.ProGuardTask::class) { outjars(proguardJarPath) printmapping("${layout.buildDirectory.get()}/proguard-mapping.txt") - dontwarn() - val javaHome = System.getProperty("java.home") if (System.getProperty("java.version").startsWith("1.")) { // Before Java 9, the runtime classes were packaged in a single jar file. diff --git a/openai-java-proguard-test/src/test/kotlin/com/openai/proguard/ProGuardCompatibilityTest.kt b/openai-java-proguard-test/src/test/kotlin/com/openai/proguard/ProGuardCompatibilityTest.kt index 5b66eb920..bf3260c7c 100644 --- a/openai-java-proguard-test/src/test/kotlin/com/openai/proguard/ProGuardCompatibilityTest.kt +++ b/openai-java-proguard-test/src/test/kotlin/com/openai/proguard/ProGuardCompatibilityTest.kt @@ -71,6 +71,7 @@ internal class ProGuardCompatibilityTest { assertThat(client.batches()).isNotNull() assertThat(client.uploads()).isNotNull() assertThat(client.responses()).isNotNull() + assertThat(client.conversations()).isNotNull() assertThat(client.evals()).isNotNull() assertThat(client.containers()).isNotNull() } diff --git a/openai-java-proguard-test/test.pro b/openai-java-proguard-test/test.pro index 24f2d49a1..026465fb0 100644 --- a/openai-java-proguard-test/test.pro +++ b/openai-java-proguard-test/test.pro @@ -5,4 +5,5 @@ -keep class org.junit.** { *; } # Many warnings don't apply for our testing purposes. +-dontnote -dontwarn \ No newline at end of file diff --git a/scripts/format b/scripts/format index 7c0be4d57..65db1769a 100755 --- a/scripts/format +++ b/scripts/format @@ -4,5 +4,18 @@ set -e cd "$(dirname "$0")/.." -echo "==> Running formatters" -./gradlew format +if command -v ktfmt &> /dev/null; then + echo "==> Running ktfmt" + ./scripts/kotlin-format +else + echo "==> Running gradlew formatKotlin" + ./gradlew formatKotlin +fi + +if command -v palantir-java-format &> /dev/null; then + echo "==> Running palantir-java-format" + ./scripts/java-format +else + echo "==> Running gradlew formatJava" + ./gradlew formatJava +fi diff --git a/scripts/java-format b/scripts/java-format new file mode 100755 index 000000000..ad5febce9 --- /dev/null +++ b/scripts/java-format @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +find . -name "*.java" -not -path "./buildSrc/build/*" -print0 | xargs -0 -r palantir-java-format --palantir --replace "$@" diff --git a/scripts/kotlin-format b/scripts/kotlin-format new file mode 100755 index 000000000..3b8be9ea9 --- /dev/null +++ b/scripts/kotlin-format @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +find . -name "*.kt" -not -path "./buildSrc/build/*" -print0 | xargs -0 -r ktfmt --kotlinlang-style "$@" diff --git a/scripts/lint b/scripts/lint index aea8af713..dbc8f7760 100755 --- a/scripts/lint +++ b/scripts/lint @@ -5,4 +5,19 @@ set -e cd "$(dirname "$0")/.." echo "==> Running lints" -./gradlew lint + +if command -v ktfmt &> /dev/null; then + echo "==> Checking ktfmt" + ./scripts/kotlin-format --dry-run --set-exit-if-changed +else + echo "==> Running gradlew lintKotlin" + ./gradlew lintKotlin +fi + +if command -v palantir-java-format &> /dev/null; then + echo "==> Checking palantir-java-format" + ./scripts/java-format --dry-run --set-exit-if-changed +else + echo "==> Running gradlew lintJava" + ./gradlew lintJava +fi