diff --git a/.gitignore b/.gitignore index b1346e6d1..90b85e944 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .prism.log +.stdy.log .gradle .idea .kotlin diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1b1593054..b85eea742 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.29.0" + ".": "4.29.1" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 05fedda9a..b6539bf3f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 151 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-55ef7034334e938c30656a404ce5e21466103be87542a796425346299f450404.yml -openapi_spec_hash: 4a5bfd2ee4ad47f5b7cf6f1ad08d5d7f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-0fea07225431c8d0cf5fc1a70c9363a91d259f7a169f410717e162de1b24e489.yml +openapi_spec_hash: 41b34c1678ec0e95daf62ca4cd52c8f8 config_hash: 96fbf82cf74a44ccd513f5acf0956ffd diff --git a/CHANGELOG.md b/CHANGELOG.md index c6278093a..789e4df47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## 4.29.1 (2026-03-23) + +Full Changelog: [v4.29.0...v4.29.1](https://github.com/openai/openai-java/compare/v4.29.0...v4.29.1) + +### Bug Fixes + +* **client:** allow updating header/query affecting fields in `toBuilder()` ([fd3b67c](https://github.com/openai/openai-java/commit/fd3b67cef9c4457506a76b9e994210e512e0181f)) +* **client:** remove redundant apiKey override ([8383a7d](https://github.com/openai/openai-java/commit/8383a7de659aa6f17e1707614f5a246ced127532)) +* **core:** format StructuredOutputs ([256718e](https://github.com/openai/openai-java/commit/256718e5ac3f3bd821d97829c5af09b2db6f113d)) +* **types:** change type field to constant in ResponseInputMessageItem ([a8ae57f](https://github.com/openai/openai-java/commit/a8ae57f73a04878013869f75bc331fa60f02b979)) + + +### Chores + +* **internal:** update gitignore ([2663595](https://github.com/openai/openai-java/commit/26635957cbcfb2438bcece6476eea1e206d54115)) +* **tests:** bump steady to v0.19.4 ([f0d4ba8](https://github.com/openai/openai-java/commit/f0d4ba8685e6376e72a928da9aaf2bdc9e1655e5)) +* **tests:** bump steady to v0.19.5 ([cbd424e](https://github.com/openai/openai-java/commit/cbd424e5e2220cc8c88522b9850fe1a923a2e523)) +* **tests:** bump steady to v0.19.6 ([28a4c27](https://github.com/openai/openai-java/commit/28a4c278d4f81e61f732d1576e09b91e85e48ca8)) + + +### Refactors + +* **tests:** switch from prism to steady ([a8cb9e8](https://github.com/openai/openai-java/commit/a8cb9e8c62c492a6aeda6fcdd6e9b09afc4f71fa)) + ## 4.29.0 (2026-03-17) Full Changelog: [v4.28.0...v4.29.0](https://github.com/openai/openai-java/compare/v4.28.0...v4.29.0) diff --git a/README.md b/README.md index fc9c39104..9ac2349ce 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/4.29.0) -[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/4.29.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/4.29.0) +[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/4.29.1) +[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/4.29.1/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/4.29.1) @@ -11,7 +11,7 @@ The OpenAI Java SDK provides convenient access to the [OpenAI REST API](https:// -The REST API documentation can be found on [platform.openai.com](https://platform.openai.com/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.openai/openai-java/4.29.0). +The REST API documentation can be found on [platform.openai.com](https://platform.openai.com/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.openai/openai-java/4.29.1). @@ -24,7 +24,7 @@ The REST API documentation can be found on [platform.openai.com](https://platfor ### Gradle ```kotlin -implementation("com.openai:openai-java:4.29.0") +implementation("com.openai:openai-java:4.29.1") ``` ### Maven @@ -33,7 +33,7 @@ implementation("com.openai:openai-java:4.29.0") com.openai openai-java - 4.29.0 + 4.29.1 ``` @@ -1342,7 +1342,7 @@ If you're using Spring Boot, then you can use the SDK's [Spring Boot starter](ht #### Gradle ```kotlin -implementation("com.openai:openai-java-spring-boot-starter:4.29.0") +implementation("com.openai:openai-java-spring-boot-starter:4.29.1") ``` #### Maven @@ -1351,7 +1351,7 @@ implementation("com.openai:openai-java-spring-boot-starter:4.29.0") com.openai openai-java-spring-boot-starter - 4.29.0 + 4.29.1 ``` diff --git a/build.gradle.kts b/build.gradle.kts index bbdcad0c8..782ec6a02 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.openai" - version = "4.29.0" // x-release-please-version + version = "4.29.1" // x-release-please-version } subprojects { diff --git a/buildSrc/src/main/kotlin/openai.kotlin.gradle.kts b/buildSrc/src/main/kotlin/openai.kotlin.gradle.kts index 4208ac263..37850353a 100644 --- a/buildSrc/src/main/kotlin/openai.kotlin.gradle.kts +++ b/buildSrc/src/main/kotlin/openai.kotlin.gradle.kts @@ -40,7 +40,7 @@ tasks.withType().configureEach { val ktfmt by configurations.creating dependencies { - ktfmt("com.facebook:ktfmt:0.56") + ktfmt("com.facebook:ktfmt:0.61") } fun registerKtfmt( 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 f1a1aff10..e48abf7bd 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 @@ -533,9 +533,7 @@ private constructor( headers.put("X-Stainless-Runtime", "JRE") headers.put("X-Stainless-Runtime-Version", getJavaVersion()) headers.put("X-Stainless-Kotlin-Version", KotlinVersion.CURRENT.toString()) - organization?.let { headers.put("OpenAI-Organization", it) } - project?.let { headers.put("OpenAI-Project", it) } - + // We replace after all the default headers to allow end-users to overwrite them. headers.replaceAll(this.headers.build()) when (credential) { is AzureApiKeyCredential -> { @@ -568,6 +566,8 @@ private constructor( } queryParams.replaceAll(this.queryParams.build()) + organization?.let { headers.replace("OpenAI-Organization", it) } + project?.let { headers.replace("OpenAI-Project", it) } return ClientOptions( httpClient, diff --git a/openai-java-core/src/main/kotlin/com/openai/core/StructuredOutputs.kt b/openai-java-core/src/main/kotlin/com/openai/core/StructuredOutputs.kt index b0198313d..36b3df529 100644 --- a/openai-java-core/src/main/kotlin/com/openai/core/StructuredOutputs.kt +++ b/openai-java-core/src/main/kotlin/com/openai/core/StructuredOutputs.kt @@ -111,11 +111,7 @@ internal fun textConfigFromClass( ResponseTextConfig.builder().format(jsonSchemaFromClass(type, localValidation)).build() // "internal" instead of "private" for testing purposes. -internal data class FunctionInfo( - val name: String, - val description: String?, - val schema: ObjectNode, -) +internal data class FunctionInfo(val name: String, val description: String?, val schema: ObjectNode) @JvmSynthetic // "internal" instead of "private" for testing purposes. diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseInputMessageItem.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseInputMessageItem.kt index 154beca64..83cccebac 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseInputMessageItem.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseInputMessageItem.kt @@ -26,8 +26,8 @@ private constructor( private val id: JsonField, private val content: JsonField>, private val role: JsonField, + private val type: JsonValue, private val status: JsonField, - private val type: JsonField, private val additionalProperties: MutableMap, ) { @@ -38,9 +38,9 @@ private constructor( @ExcludeMissing content: JsonField> = JsonMissing.of(), @JsonProperty("role") @ExcludeMissing role: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), - @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), - ) : this(id, content, role, status, type, mutableMapOf()) + ) : this(id, content, role, type, status, mutableMapOf()) /** * The unique ID of the message input. @@ -67,21 +67,26 @@ private constructor( fun role(): Role = role.getRequired("role") /** - * The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items - * are returned via API. + * The type of the message input. Always set to `message`. * - * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). + * 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). */ - fun status(): Optional = status.getOptional("status") + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type /** - * The type of the message input. Always set to `message`. + * 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 (e.g. if the * server responded with an unexpected value). */ - fun type(): Optional = type.getOptional("type") + fun status(): Optional = status.getOptional("status") /** * Returns the raw JSON value of [id]. @@ -113,13 +118,6 @@ private constructor( */ @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status - /** - * Returns the raw JSON value of [type]. - * - * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type - @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -153,8 +151,8 @@ private constructor( private var id: JsonField? = null private var content: JsonField>? = null private var role: JsonField? = null + private var type: JsonValue = JsonValue.from("message") private var status: JsonField = JsonMissing.of() - private var type: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -162,8 +160,8 @@ private constructor( id = responseInputMessageItem.id content = responseInputMessageItem.content.map { it.toMutableList() } role = responseInputMessageItem.role - status = responseInputMessageItem.status type = responseInputMessageItem.type + status = responseInputMessageItem.status additionalProperties = responseInputMessageItem.additionalProperties.toMutableMap() } @@ -249,6 +247,20 @@ private constructor( */ fun role(role: JsonField) = apply { this.role = role } + /** + * 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 } + /** * The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when * items are returned via API. @@ -263,17 +275,6 @@ private constructor( */ fun status(status: JsonField) = apply { this.status = status } - /** The type of the message input. Always set to `message`. */ - fun type(type: Type) = type(JsonField.of(type)) - - /** - * Sets [Builder.type] to an arbitrary JSON value. - * - * You should usually call [Builder.type] with a well-typed [Type] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun type(type: JsonField) = apply { this.type = type } - fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -312,8 +313,8 @@ private constructor( checkRequired("id", id), checkRequired("content", content).map { it.toImmutable() }, checkRequired("role", role), - status, type, + status, additionalProperties.toMutableMap(), ) } @@ -328,8 +329,12 @@ private constructor( id() content().forEach { it.validate() } role().validate() + _type().let { + if (it != JsonValue.from("message")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } status().ifPresent { it.validate() } - type().ifPresent { it.validate() } validated = true } @@ -351,8 +356,8 @@ private constructor( (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.asKnown().getOrNull()?.validity() ?: 0) + type.let { if (it == JsonValue.from("message")) 1 else 0 } + + (status.asKnown().getOrNull()?.validity() ?: 0) /** The role of the message input. One of `user`, `system`, or `developer`. */ class Role @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -621,126 +626,6 @@ private constructor( override fun toString() = value.toString() } - /** The type of the message input. Always set to `message`. */ - class Type @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 MESSAGE = of("message") - - @JvmStatic fun of(value: String) = Type(JsonField.of(value)) - } - - /** An enum containing [Type]'s known values. */ - enum class Known { - MESSAGE - } - - /** - * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [Type] 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 { - MESSAGE, - /** An enum member indicating that [Type] 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) { - MESSAGE -> Value.MESSAGE - 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) { - MESSAGE -> Known.MESSAGE - else -> throw OpenAIInvalidDataException("Unknown Type: $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(): Type = 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 Type && value == other.value - } - - override fun hashCode() = value.hashCode() - - override fun toString() = value.toString() - } - override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -750,17 +635,17 @@ private constructor( id == other.id && content == other.content && role == other.role && - status == other.status && type == other.type && + status == other.status && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(id, content, role, status, type, additionalProperties) + Objects.hash(id, content, role, type, status, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "ResponseInputMessageItem{id=$id, content=$content, role=$role, status=$status, type=$type, additionalProperties=$additionalProperties}" + "ResponseInputMessageItem{id=$id, content=$content, role=$role, type=$type, status=$status, additionalProperties=$additionalProperties}" } diff --git a/openai-java-core/src/test/kotlin/com/openai/core/ClientOptionsTest.kt b/openai-java-core/src/test/kotlin/com/openai/core/ClientOptionsTest.kt index 9aef24029..74ab42f4a 100644 --- a/openai-java-core/src/test/kotlin/com/openai/core/ClientOptionsTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/core/ClientOptionsTest.kt @@ -16,6 +16,44 @@ internal class ClientOptionsTest { private val httpClient = mock() + @Test + fun putHeader_canOverwriteDefaultHeader() { + val clientOptions = + ClientOptions.builder() + .httpClient(httpClient) + .putHeader("User-Agent", "My User Agent") + .apiKey("My API Key") + .build() + + assertThat(clientOptions.headers.values("User-Agent")).containsExactly("My User Agent") + } + + @Test + fun toBuilder_organizationCanBeUpdated() { + var clientOptions = + ClientOptions.builder() + .httpClient(httpClient) + .organization("My Organization") + .apiKey("My API Key") + .build() + + clientOptions = clientOptions.toBuilder().organization("another My Organization").build() + + assertThat(clientOptions.headers.values("OpenAI-Organization")) + .containsExactly("another My Organization") + } + + @Test + fun toBuilder_bearerAuthCanBeUpdated() { + var clientOptions = + ClientOptions.builder().httpClient(httpClient).apiKey("My API Key").build() + + clientOptions = clientOptions.toBuilder().apiKey("another My API Key").build() + + assertThat(clientOptions.headers.values("Authorization")) + .containsExactly("Bearer another My API Key") + } + @Test fun toBuilder_whenOriginalClientOptionsGarbageCollected_doesNotCloseOriginalClient() { var clientOptions = diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseInputMessageItemTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseInputMessageItemTest.kt index 1ddefa101..2eb6f128e 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseInputMessageItemTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseInputMessageItemTest.kt @@ -17,7 +17,6 @@ internal class ResponseInputMessageItemTest { .addInputTextContent("text") .role(ResponseInputMessageItem.Role.USER) .status(ResponseInputMessageItem.Status.IN_PROGRESS) - .type(ResponseInputMessageItem.Type.MESSAGE) .build() assertThat(responseInputMessageItem.id()).isEqualTo("id") @@ -28,7 +27,6 @@ internal class ResponseInputMessageItemTest { assertThat(responseInputMessageItem.role()).isEqualTo(ResponseInputMessageItem.Role.USER) assertThat(responseInputMessageItem.status()) .contains(ResponseInputMessageItem.Status.IN_PROGRESS) - assertThat(responseInputMessageItem.type()).contains(ResponseInputMessageItem.Type.MESSAGE) } @Test @@ -40,7 +38,6 @@ internal class ResponseInputMessageItemTest { .addInputTextContent("text") .role(ResponseInputMessageItem.Role.USER) .status(ResponseInputMessageItem.Status.IN_PROGRESS) - .type(ResponseInputMessageItem.Type.MESSAGE) .build() val roundtrippedResponseInputMessageItem = diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseItemTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseItemTest.kt index 2c76ea3db..cdc7e6958 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseItemTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseItemTest.kt @@ -22,7 +22,6 @@ internal class ResponseItemTest { .addInputTextContent("text") .role(ResponseInputMessageItem.Role.USER) .status(ResponseInputMessageItem.Status.IN_PROGRESS) - .type(ResponseInputMessageItem.Type.MESSAGE) .build() val responseItem = ResponseItem.ofResponseInputMessageItem(responseInputMessageItem) @@ -61,7 +60,6 @@ internal class ResponseItemTest { .addInputTextContent("text") .role(ResponseInputMessageItem.Role.USER) .status(ResponseInputMessageItem.Status.IN_PROGRESS) - .type(ResponseInputMessageItem.Type.MESSAGE) .build() ) diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/inputitems/ResponseItemListTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/inputitems/ResponseItemListTest.kt index e5cd6b8f2..3ea4d4166 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/inputitems/ResponseItemListTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/inputitems/ResponseItemListTest.kt @@ -21,7 +21,6 @@ internal class ResponseItemListTest { .addInputTextContent("text") .role(ResponseInputMessageItem.Role.USER) .status(ResponseInputMessageItem.Status.IN_PROGRESS) - .type(ResponseInputMessageItem.Type.MESSAGE) .build() ) .firstId("first_id") @@ -37,7 +36,6 @@ internal class ResponseItemListTest { .addInputTextContent("text") .role(ResponseInputMessageItem.Role.USER) .status(ResponseInputMessageItem.Status.IN_PROGRESS) - .type(ResponseInputMessageItem.Type.MESSAGE) .build() ) ) @@ -57,7 +55,6 @@ internal class ResponseItemListTest { .addInputTextContent("text") .role(ResponseInputMessageItem.Role.USER) .status(ResponseInputMessageItem.Status.IN_PROGRESS) - .type(ResponseInputMessageItem.Type.MESSAGE) .build() ) .firstId("first_id") diff --git a/scripts/fast-format b/scripts/fast-format index 1b3bc473a..35a1dee25 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -24,8 +24,8 @@ if [ ! -f "$FILE_LIST" ]; then exit 1 fi -if ! command -v ktfmt-fast-format &> /dev/null; then - echo "Error: ktfmt-fast-format not found" +if ! command -v ktfmt &> /dev/null; then + echo "Error: ktfmt not found" exit 1 fi @@ -36,7 +36,7 @@ echo "==> Done looking for Kotlin files" if [[ -n "$kt_files" ]]; then echo "==> will format Kotlin files" - echo "$kt_files" | tr '\n' '\0' | xargs -0 ktfmt-fast-format --kotlinlang-style "$@" + echo "$kt_files" | tr '\n' '\0' | xargs -0 ktfmt --kotlinlang-style "$@" else echo "No Kotlin files to format -- expected outcome during incremental formatting" fi diff --git a/scripts/mock b/scripts/mock index bcf3b392b..dba305898 100755 --- a/scripts/mock +++ b/scripts/mock @@ -19,34 +19,34 @@ fi echo "==> Starting mock server with URL ${URL}" -# Run prism mock on the given spec +# Run steady mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism --version + npm exec --package=@stdy/cli@0.19.6 -- steady --version - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & + npm exec --package=@stdy/cli@0.19.6 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=brackets --validator-query-array-format=brackets --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log & - # Wait for server to come online (max 30s) + # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" attempts=0 - while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + while ! curl --silent --fail "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1; do + if ! kill -0 $! 2>/dev/null; then + echo + cat .stdy.log + exit 1 + fi attempts=$((attempts + 1)) if [ "$attempts" -ge 300 ]; then echo - echo "Timed out waiting for Prism server to start" - cat .prism.log + echo "Timed out waiting for Steady server to start" + cat .stdy.log exit 1 fi echo -n "." sleep 0.1 done - if grep -q "✖ fatal" ".prism.log"; then - cat .prism.log - exit 1 - fi - echo else - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" + npm exec --package=@stdy/cli@0.19.6 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=brackets --validator-query-array-format=brackets --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index d0126f840..23923e374 100755 --- a/scripts/test +++ b/scripts/test @@ -9,8 +9,8 @@ GREEN='\033[0;32m' YELLOW='\033[0;33m' NC='\033[0m' # No Color -function prism_is_running() { - curl --silent "http://localhost:4010" >/dev/null 2>&1 +function steady_is_running() { + curl --silent "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1 } kill_server_on_port() { @@ -25,7 +25,7 @@ function is_overriding_api_base_url() { [ -n "$TEST_API_BASE_URL" ] } -if ! is_overriding_api_base_url && ! prism_is_running ; then +if ! is_overriding_api_base_url && ! steady_is_running ; then # When we exit this script, make sure to kill the background mock server process trap 'kill_server_on_port 4010' EXIT @@ -36,19 +36,19 @@ fi if is_overriding_api_base_url ; then echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" echo -elif ! prism_is_running ; then - echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" +elif ! steady_is_running ; then + echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Steady server" echo -e "running against your OpenAPI spec." echo echo -e "To run the server, pass in the path or url of your OpenAPI" - echo -e "spec to the prism command:" + echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.6 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=brackets --validator-query-array-format=brackets --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}" echo exit 1 else - echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" + echo -e "${GREEN}✔ Mock steady server is running with your OpenAPI spec${NC}" echo fi