From 1e4b24222e7404fdbb9111e9c6919663d10eed9e Mon Sep 17 00:00:00 2001 From: Daymon Date: Tue, 28 May 2024 13:01:40 -0500 Subject: [PATCH 1/2] Make the migration --- .gitignore | 3 + build.gradle.kts | 3 +- common/build.gradle.kts | 118 ++++++++---------- common/gradle.properties | 2 + .../{main => androidMain}/AndroidManifest.xml | 0 .../common/APIController.android.kt | 22 ++++ .../common/util/kotlin.android.kt | 21 ++++ .../common/util/logging.android.kt | 27 ++++ .../common/util/serialization.android.kt} | 34 +++-- .../generativeai/common/APIController.kt | 17 +-- .../client/generativeai/common/Exceptions.kt | 0 .../ai/client/generativeai/common/Request.kt | 0 .../generativeai/common/RequestOptions.kt | 0 .../ai/client/generativeai/common/Response.kt | 4 +- .../generativeai/common/client/Types.kt | 8 +- .../generativeai/common/server/Types.kt | 10 +- .../generativeai/common/shared/Types.kt | 8 +- .../client/generativeai/common/util/kotlin.kt | 21 ++++ .../client/generativeai/common/util/ktor.kt | 0 .../generativeai/common/util/logging.kt | 21 ++++ .../generativeai/common/util/serialization.kt | 16 ++- .../generativeai/common/APIController.jvm.kt | 22 ++++ .../generativeai/common/util/kotlin.jvm.kt | 21 ++++ .../generativeai/common/util/logging.jvm.kt | 25 ++++ .../common/util/serialization.jvm.kt | 50 ++++++++ .../generativeai/common/APIControllerTests.kt | 24 ++-- .../common/StreamingSnapshotTests.kt | 0 .../generativeai/common/UnarySnapshotTests.kt | 0 .../client/generativeai/common/util/kotlin.kt | 0 .../client/generativeai/common/util/tests.kt | 10 +- .../streaming/failure-api-key.txt | 0 .../streaming/failure-empty-content.txt | 0 .../failure-finish-reason-safety.txt | 0 .../streaming/failure-http-error.txt | 0 .../streaming/failure-image-rejected.txt | 0 .../failure-prompt-blocked-safety.txt | 0 .../failure-recitation-no-content.txt | 0 .../streaming/failure-unknown-model.txt | 0 .../streaming/success-basic-reply-long.txt | 0 .../streaming/success-basic-reply-short.txt | 0 .../streaming/success-citations-altname.txt | 0 .../streaming/success-citations.txt | 0 .../streaming/success-quotes-escaped.txt | 0 .../streaming/success-unknown-enum.txt | 0 .../golden-files/unary/failure-api-key.json | 0 .../unary/failure-empty-content.json | 0 .../unary/failure-finish-reason-safety.json | 0 .../unary/failure-http-error.json | 0 .../unary/failure-image-rejected.json | 0 .../unary/failure-invalid-response.json | 0 .../unary/failure-malformed-content.json | 0 .../unary/failure-prompt-blocked-safety.json | 0 .../unary/failure-quota-exceeded.json | 0 .../unary/failure-unknown-model.json | 0 .../failure-unsupported-user-location.json | 0 .../unary/success-basic-reply-long.json | 0 .../unary/success-basic-reply-short.json | 0 .../unary/success-citations-altname.json | 0 .../unary/success-citations-nolicense.json | 0 .../golden-files/unary/success-citations.json | 0 .../success-constraint-decoding-json.json | 0 .../unary/success-including-severity.json | 0 .../unary/success-partial-usage-metadata.json | 0 .../unary/success-quote-reply.json | 0 .../unary/success-unknown-enum.json | 0 .../unary/success-usage-metadata.json | 0 .../generativeai/internal/util/conversions.kt | 9 +- .../ai/client/generativeai/type/Candidate.kt | 4 +- .../type/GenerateContentResponse.kt | 2 +- .../generativeai/type/GenerationConfig.kt | 4 +- .../generativeai/type/PromptFeedback.kt | 5 +- .../generativeai/type/RequestOptions.kt | 10 +- .../ai/client/generativeai/type/Tool.kt | 4 +- .../client/generativeai/type/UsageMetadata.kt | 2 +- .../GenerateContentResponseTest.kt | 12 +- .../generativeai/GenerativeModelTests.kt | 25 ++-- gradle/wrapper/gradle-wrapper.properties | 4 +- plugins/build.gradle.kts | 6 +- .../com/google/gradle/plugins/ApiPlugin.kt | 5 +- .../java/com/google/gradle/util/gradle.kt | 26 ++-- settings.gradle.kts | 3 +- 81 files changed, 405 insertions(+), 203 deletions(-) rename common/src/{main => androidMain}/AndroidManifest.xml (100%) create mode 100644 common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/APIController.android.kt create mode 100644 common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/util/kotlin.android.kt create mode 100644 common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/util/logging.android.kt rename common/src/{main/kotlin/com/google/ai/client/generativeai/common/util/kotlin.kt => androidMain/kotlin/com/google/ai/client/generativeai/common/util/serialization.android.kt} (51%) rename common/src/{main => commonMain}/kotlin/com/google/ai/client/generativeai/common/APIController.kt (94%) rename common/src/{main => commonMain}/kotlin/com/google/ai/client/generativeai/common/Exceptions.kt (100%) rename common/src/{main => commonMain}/kotlin/com/google/ai/client/generativeai/common/Request.kt (100%) rename common/src/{main => commonMain}/kotlin/com/google/ai/client/generativeai/common/RequestOptions.kt (100%) rename common/src/{main => commonMain}/kotlin/com/google/ai/client/generativeai/common/Response.kt (94%) rename common/src/{main => commonMain}/kotlin/com/google/ai/client/generativeai/common/client/Types.kt (94%) rename common/src/{main => commonMain}/kotlin/com/google/ai/client/generativeai/common/server/Types.kt (95%) rename common/src/{main => commonMain}/kotlin/com/google/ai/client/generativeai/common/shared/Types.kt (95%) create mode 100644 common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/util/kotlin.kt rename common/src/{main => commonMain}/kotlin/com/google/ai/client/generativeai/common/util/ktor.kt (100%) create mode 100644 common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/util/logging.kt rename common/src/{main => commonMain}/kotlin/com/google/ai/client/generativeai/common/util/serialization.kt (86%) create mode 100644 common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/APIController.jvm.kt create mode 100644 common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/kotlin.jvm.kt create mode 100644 common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/logging.jvm.kt create mode 100644 common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/serialization.jvm.kt rename common/src/{test/java => jvmTest/kotlin}/com/google/ai/client/generativeai/common/APIControllerTests.kt (98%) rename common/src/{test/java => jvmTest/kotlin}/com/google/ai/client/generativeai/common/StreamingSnapshotTests.kt (100%) rename common/src/{test/java => jvmTest/kotlin}/com/google/ai/client/generativeai/common/UnarySnapshotTests.kt (100%) rename common/src/{test/java => jvmTest/kotlin}/com/google/ai/client/generativeai/common/util/kotlin.kt (100%) rename common/src/{test/java => jvmTest/kotlin}/com/google/ai/client/generativeai/common/util/tests.kt (97%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/failure-api-key.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/failure-empty-content.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/failure-finish-reason-safety.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/failure-http-error.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/failure-image-rejected.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/failure-prompt-blocked-safety.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/failure-recitation-no-content.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/failure-unknown-model.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/success-basic-reply-long.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/success-basic-reply-short.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/success-citations-altname.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/success-citations.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/success-quotes-escaped.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/streaming/success-unknown-enum.txt (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/failure-api-key.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/failure-empty-content.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/failure-finish-reason-safety.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/failure-http-error.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/failure-image-rejected.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/failure-invalid-response.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/failure-malformed-content.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/failure-prompt-blocked-safety.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/failure-quota-exceeded.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/failure-unknown-model.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/failure-unsupported-user-location.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/success-basic-reply-long.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/success-basic-reply-short.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/success-citations-altname.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/success-citations-nolicense.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/success-citations.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/success-constraint-decoding-json.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/success-including-severity.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/success-partial-usage-metadata.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/success-quote-reply.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/success-unknown-enum.json (100%) rename common/src/{test => jvmTest}/resources/golden-files/unary/success-usage-metadata.json (100%) diff --git a/.gitignore b/.gitignore index 347e252e..b8ed8387 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ .gradle/ build/ +# KMP files +.kotlin/ + # Local configuration file (sdk path, etc) local.properties diff --git a/build.gradle.kts b/build.gradle.kts index 348fc881..726b27b9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,8 +18,9 @@ plugins { id("com.android.library") version "8.1.3" apply false id("org.jetbrains.dokka") version "1.8.20" apply false kotlin("android") version "1.8.22" apply false + kotlin("multiplatform") version "2.0.0" apply false kotlin("plugin.serialization") version "1.8.22" apply false - id("com.ncorti.ktfmt.gradle") version "0.16.0" apply false + id("com.ncorti.ktfmt.gradle") version "0.18.0" apply false id("license-plugin") id("multi-project-plugin") } diff --git a/common/build.gradle.kts b/common/build.gradle.kts index bd02f5fa..6ee0cb3c 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -14,13 +14,19 @@ * limitations under the License. */ +@file:Suppress("UnstableApiUsage") +@file:OptIn(ExperimentalKotlinGradlePluginApi::class) + +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.dsl.KotlinVersion + plugins { - id("com.android.library") + id("com.android.kotlin.multiplatform.library") // version "8.6.0-alpha02" + kotlin("multiplatform") version "2.0.0" id("maven-publish") - id("com.ncorti.ktfmt.gradle") + id("com.ncorti.ktfmt.gradle") version "0.18.0" id("changelog-plugin") id("release-plugin") - kotlin("android") kotlin("plugin.serialization") } @@ -28,75 +34,54 @@ ktfmt { googleStyle() } -android { - namespace = "com.google.ai.client.generativeai.common" - compileSdk = 34 - - buildFeatures.buildConfig = true - - defaultConfig { +kotlin { + val ktorVersion = "2.3.2" + androidLibrary { + compileSdk = 34 minSdk = 21 - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - - buildConfigField("String", "VERSION_NAME", "\"${project.version.toString()}\"") - } - - publishing { - singleVariant("release") { - withSourcesJar() + namespace = "com.google.ai.client.generativeai.common" + optimization { + minify = false + consumerKeepRules.file("consumer-rules.pro") + consumerKeepRules.publish = true } - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) + withAndroidTestOnJvm { + isReturnDefaultValues = true } } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - kotlinOptions { - jvmTarget = "17" + jvmToolchain(17) + compilerOptions { + apiVersion.set(KotlinVersion.KOTLIN_1_8) + languageVersion.set(KotlinVersion.KOTLIN_1_8) } - testOptions { - unitTests.isReturnDefaultValues = true - } -} - -dependencies { - val ktorVersion = "2.3.2" - - implementation("io.ktor:ktor-client-okhttp:$ktorVersion") - implementation("io.ktor:ktor-client-core:$ktorVersion") - implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") - implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion") - implementation("io.ktor:ktor-client-logging:$ktorVersion") - - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1") - implementation("androidx.core:core-ktx:1.12.0") - implementation("org.slf4j:slf4j-nop:2.0.9") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.7.3") - implementation("org.reactivestreams:reactive-streams:1.0.3") + jvm() + sourceSets { + commonMain.dependencies { + implementation("io.ktor:ktor-client-core:$ktorVersion") + implementation("org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22") + implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") + implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion") + implementation("io.ktor:ktor-client-logging:$ktorVersion") - implementation("com.google.guava:listenablefuture:1.0") - implementation("androidx.concurrent:concurrent-futures:1.2.0-alpha02") - implementation("androidx.concurrent:concurrent-futures-ktx:1.2.0-alpha02") - testImplementation("junit:junit:4.13.2") - testImplementation("io.kotest:kotest-assertions-core:4.0.7") - testImplementation("io.kotest:kotest-assertions-jvm:4.0.7") - testImplementation("io.kotest:kotest-assertions-json:4.0.7") - testImplementation("io.ktor:ktor-client-mock:$ktorVersion") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1") + implementation("org.slf4j:slf4j-nop:2.0.9") + } + androidMain.dependencies { + implementation("io.ktor:ktor-client-okhttp:$ktorVersion") + implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.22") + } + jvmMain.dependencies { + implementation("io.ktor:ktor-client-okhttp:$ktorVersion") + implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.22") + } + jvmTest.dependencies { + implementation("junit:junit:4.13.2") + implementation("io.kotest:kotest-assertions-core-jvm:4.0.7") + implementation("io.kotest:kotest-assertions-json-jvm:4.0.7") + implementation("io.ktor:ktor-client-mock-jvm:$ktorVersion") + } + } } publishing { @@ -113,9 +98,6 @@ publishing { } } } - afterEvaluate { - from(components["release"]) - } } } repositories { diff --git a/common/gradle.properties b/common/gradle.properties index 59a78457..d8f410ab 100644 --- a/common/gradle.properties +++ b/common/gradle.properties @@ -1 +1,3 @@ version=0.5.0 +kotlin.mpp.androidSourceSetLayoutVersion=2 +kotlin.compiler.runViaBuildToolsApi=true diff --git a/common/src/main/AndroidManifest.xml b/common/src/androidMain/AndroidManifest.xml similarity index 100% rename from common/src/main/AndroidManifest.xml rename to common/src/androidMain/AndroidManifest.xml diff --git a/common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/APIController.android.kt b/common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/APIController.android.kt new file mode 100644 index 00000000..1c53db76 --- /dev/null +++ b/common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/APIController.android.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.ai.client.generativeai.common + +import io.ktor.client.engine.HttpClientEngine +import io.ktor.client.engine.okhttp.OkHttp + +internal actual fun createHttpClient(): HttpClientEngine = OkHttp.create() diff --git a/common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/util/kotlin.android.kt b/common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/util/kotlin.android.kt new file mode 100644 index 00000000..59b398eb --- /dev/null +++ b/common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/util/kotlin.android.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.ai.client.generativeai.common.util + +import kotlin.reflect.KClass + +internal actual inline fun KClass.name(): String = java.name diff --git a/common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/util/logging.android.kt b/common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/util/logging.android.kt new file mode 100644 index 00000000..7ef76222 --- /dev/null +++ b/common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/util/logging.android.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.ai.client.generativeai.common.util + +import android.util.Log + +internal actual fun Error(tag: String, message: String) { + Log.e(tag, message) +} + +internal actual fun Warning(tag: String, message: String) { + Log.w(tag, message) +} diff --git a/common/src/main/kotlin/com/google/ai/client/generativeai/common/util/kotlin.kt b/common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/util/serialization.android.kt similarity index 51% rename from common/src/main/kotlin/com/google/ai/client/generativeai/common/util/kotlin.kt rename to common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/util/serialization.android.kt index 8f681542..5b425f25 100644 --- a/common/src/main/kotlin/com/google/ai/client/generativeai/common/util/kotlin.kt +++ b/common/src/androidMain/kotlin/com/google/ai/client/generativeai/common/util/serialization.android.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,19 +16,10 @@ package com.google.ai.client.generativeai.common.util +import com.google.ai.client.generativeai.common.SerializationException +import kotlinx.serialization.SerialName import java.lang.reflect.Field - -/** - * Removes the last character from the [StringBuilder]. - * - * If the StringBuilder is empty, calling this function will throw an [IndexOutOfBoundsException]. - * - * @return The [StringBuilder] used to make the call, for optional chaining. - * @throws IndexOutOfBoundsException if the StringBuilder is empty. - */ -internal fun StringBuilder.removeLast(): StringBuilder = - if (isEmpty()) throw IndexOutOfBoundsException("StringBuilder is empty.") - else deleteCharAt(length - 1) +import kotlin.reflect.KClass /** * A variant of [getAnnotation][Field.getAnnotation] that provides implicit Kotlin support. @@ -39,3 +30,20 @@ internal fun StringBuilder.removeLast(): StringBuilder = * ``` */ internal inline fun Field.getAnnotation() = getAnnotation(T::class.java) + + +/** + * Provides the name to be used in serialization for this enum value. + * + * By default an enum is serialized to its [name][Enum.name], and can be overwritten by providing a + * [SerialName] annotation. + */ +internal actual fun > T.serialName(): String = declaringJavaClass.getField(name).getAnnotation()?.value ?: name + +/** + * Variant of [kotlin.enumValues] that provides support for [KClass] instances of enums. + * + * @throws SerializationException if the class is not a valid enum. Beyond runtime emily magic, this + * shouldn't really be possible. + */ +internal actual fun > KClass.enumValues(): Array = java.enumConstants ?: throw SerializationException("$simpleName is not a valid enum type.") diff --git a/common/src/main/kotlin/com/google/ai/client/generativeai/common/APIController.kt b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/APIController.kt similarity index 94% rename from common/src/main/kotlin/com/google/ai/client/generativeai/common/APIController.kt rename to common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/APIController.kt index ba331325..103d6b98 100644 --- a/common/src/main/kotlin/com/google/ai/client/generativeai/common/APIController.kt +++ b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/APIController.kt @@ -16,13 +16,14 @@ package com.google.ai.client.generativeai.common -import android.util.Log +// import android.util.Log import com.google.ai.client.generativeai.common.server.FinishReason +import com.google.ai.client.generativeai.common.util.Warning import com.google.ai.client.generativeai.common.util.decodeToFlow +import com.google.ai.client.generativeai.common.util.name import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.engine.HttpClientEngine -import io.ktor.client.engine.okhttp.OkHttp import io.ktor.client.plugins.HttpTimeout import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.client.request.HttpRequestBuilder @@ -53,6 +54,8 @@ internal val JSON = Json { prettyPrint = false } +internal expect fun createHttpClient(): HttpClientEngine + /** * Backend class for interfacing with the Gemini API. * @@ -72,7 +75,7 @@ internal constructor( private val requestOptions: RequestOptions, httpEngine: HttpClientEngine, private val apiClient: String, - private val headerProvider: HeaderProvider? + private val headerProvider: HeaderProvider?, ) { constructor( @@ -80,8 +83,8 @@ internal constructor( model: String, requestOptions: RequestOptions, apiClient: String, - headerProvider: HeaderProvider? = null - ) : this(key, model, requestOptions, OkHttp.create(), apiClient, headerProvider) + headerProvider: HeaderProvider? = null, + ) : this(key, model, requestOptions, createHttpClient(), apiClient, headerProvider) private val model = fullModelName(model) @@ -150,7 +153,7 @@ internal constructor( } } } catch (e: TimeoutCancellationException) { - Log.w(TAG, "HeaderProvided timed out without generating headers, ignoring") + Warning(TAG, "HeaderProvided timed out without generating headers, ignoring") } } } @@ -203,7 +206,7 @@ internal constructor( } companion object { - private val TAG = APIController::class.java.simpleName + private val TAG = APIController::class.name() } } diff --git a/common/src/main/kotlin/com/google/ai/client/generativeai/common/Exceptions.kt b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/Exceptions.kt similarity index 100% rename from common/src/main/kotlin/com/google/ai/client/generativeai/common/Exceptions.kt rename to common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/Exceptions.kt diff --git a/common/src/main/kotlin/com/google/ai/client/generativeai/common/Request.kt b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/Request.kt similarity index 100% rename from common/src/main/kotlin/com/google/ai/client/generativeai/common/Request.kt rename to common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/Request.kt diff --git a/common/src/main/kotlin/com/google/ai/client/generativeai/common/RequestOptions.kt b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/RequestOptions.kt similarity index 100% rename from common/src/main/kotlin/com/google/ai/client/generativeai/common/RequestOptions.kt rename to common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/RequestOptions.kt diff --git a/common/src/main/kotlin/com/google/ai/client/generativeai/common/Response.kt b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/Response.kt similarity index 94% rename from common/src/main/kotlin/com/google/ai/client/generativeai/common/Response.kt rename to common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/Response.kt index e3885bfd..8b5f1ba7 100644 --- a/common/src/main/kotlin/com/google/ai/client/generativeai/common/Response.kt +++ b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/Response.kt @@ -27,7 +27,7 @@ sealed interface Response data class GenerateContentResponse( val candidates: List? = null, val promptFeedback: PromptFeedback? = null, - val usageMetadata: UsageMetadata? = null + val usageMetadata: UsageMetadata? = null, ) : Response @Serializable @@ -40,5 +40,5 @@ data class CountTokensResponse(val totalTokens: Int, val totalBillableCharacters data class UsageMetadata( val promptTokenCount: Int? = null, val candidatesTokenCount: Int? = null, - val totalTokenCount: Int? = null + val totalTokenCount: Int? = null, ) diff --git a/common/src/main/kotlin/com/google/ai/client/generativeai/common/client/Types.kt b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/client/Types.kt similarity index 94% rename from common/src/main/kotlin/com/google/ai/client/generativeai/common/client/Types.kt rename to common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/client/Types.kt index aeb59ad5..8a5c4604 100644 --- a/common/src/main/kotlin/com/google/ai/client/generativeai/common/client/Types.kt +++ b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/client/Types.kt @@ -27,7 +27,7 @@ data class GenerationConfig( @SerialName("candidate_count") val candidateCount: Int?, @SerialName("max_output_tokens") val maxOutputTokens: Int?, @SerialName("stop_sequences") val stopSequences: List?, - @SerialName("response_mime_type") val responseMimeType: String? + @SerialName("response_mime_type") val responseMimeType: String?, ) @Serializable data class Tool(val functionDeclarations: List) @@ -49,11 +49,7 @@ data class FunctionCallingConfig(val mode: Mode) { } @Serializable -data class FunctionDeclaration( - val name: String, - val description: String, - val parameters: Schema, -) +data class FunctionDeclaration(val name: String, val description: String, val parameters: Schema) @Serializable data class Schema( diff --git a/common/src/main/kotlin/com/google/ai/client/generativeai/common/server/Types.kt b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/server/Types.kt similarity index 95% rename from common/src/main/kotlin/com/google/ai/client/generativeai/common/server/Types.kt rename to common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/server/Types.kt index c7649153..85a7c102 100644 --- a/common/src/main/kotlin/com/google/ai/client/generativeai/common/server/Types.kt +++ b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/server/Types.kt @@ -53,7 +53,7 @@ data class Candidate( val content: Content? = null, val finishReason: FinishReason? = null, val safetyRatings: List? = null, - val citationMetadata: CitationMetadata? = null + val citationMetadata: CitationMetadata? = null, ) @Serializable @@ -66,7 +66,7 @@ data class CitationSources( val startIndex: Int = 0, val endIndex: Int, val uri: String, - val license: String? = null + val license: String? = null, ) @Serializable @@ -110,8 +110,4 @@ enum class FinishReason { OTHER } -@Serializable -data class GRpcError( - val code: Int, - val message: String, -) +@Serializable data class GRpcError(val code: Int, val message: String) diff --git a/common/src/main/kotlin/com/google/ai/client/generativeai/common/shared/Types.kt b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/shared/Types.kt similarity index 95% rename from common/src/main/kotlin/com/google/ai/client/generativeai/common/shared/Types.kt rename to common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/shared/Types.kt index d10bdf36..09a35739 100644 --- a/common/src/main/kotlin/com/google/ai/client/generativeai/common/shared/Types.kt +++ b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/shared/Types.kt @@ -66,14 +66,10 @@ data class Content(@EncodeDefault val role: String? = "user", val parts: List KClass.name(): String diff --git a/common/src/main/kotlin/com/google/ai/client/generativeai/common/util/ktor.kt b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/util/ktor.kt similarity index 100% rename from common/src/main/kotlin/com/google/ai/client/generativeai/common/util/ktor.kt rename to common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/util/ktor.kt diff --git a/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/util/logging.kt b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/util/logging.kt new file mode 100644 index 00000000..e2eebd97 --- /dev/null +++ b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/util/logging.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.ai.client.generativeai.common.util + +internal expect fun Error(tag: String, message: String) + +internal expect fun Warning(tag: String, message: String) diff --git a/common/src/main/kotlin/com/google/ai/client/generativeai/common/util/serialization.kt b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/util/serialization.kt similarity index 86% rename from common/src/main/kotlin/com/google/ai/client/generativeai/common/util/serialization.kt rename to common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/util/serialization.kt index d818c266..abb88059 100644 --- a/common/src/main/kotlin/com/google/ai/client/generativeai/common/util/serialization.kt +++ b/common/src/commonMain/kotlin/com/google/ai/client/generativeai/common/util/serialization.kt @@ -16,7 +16,7 @@ package com.google.ai.client.generativeai.common.util -import android.util.Log +// import android.util.Log import com.google.ai.client.generativeai.common.SerializationException import kotlin.reflect.KClass import kotlinx.serialization.KSerializer @@ -41,12 +41,12 @@ class FirstOrdinalSerializer>(private val enumClass: KClass) : KS val name = decoder.decodeString() val values = enumClass.enumValues() - return values.firstOrNull { it.serialName == name } + return values.firstOrNull { it.serialName() == name } ?: values.first().also { printWarning(name) } } private fun printWarning(name: String) { - Log.e( + Error( "FirstOrdinalSerializer", """ |Unknown enum value found: $name" @@ -55,12 +55,12 @@ class FirstOrdinalSerializer>(private val enumClass: KClass) : KS |GitHub to bring it to our attention: |https://github.com/google/google-ai-android """ - .trimMargin() + .trimMargin(), ) } override fun serialize(encoder: Encoder, value: T) { - encoder.encodeString(value.serialName) + encoder.encodeString(value.serialName()) } } @@ -70,8 +70,7 @@ class FirstOrdinalSerializer>(private val enumClass: KClass) : KS * By default an enum is serialized to its [name][Enum.name], and can be overwritten by providing a * [SerialName] annotation. */ -val > T.serialName: String - get() = declaringJavaClass.getField(name).getAnnotation()?.value ?: name +internal expect fun > T.serialName(): String /** * Variant of [kotlin.enumValues] that provides support for [KClass] instances of enums. @@ -79,5 +78,4 @@ val > T.serialName: String * @throws SerializationException if the class is not a valid enum. Beyond runtime emily magic, this * shouldn't really be possible. */ -fun > KClass.enumValues(): Array = - java.enumConstants ?: throw SerializationException("$simpleName is not a valid enum type.") +internal expect fun > KClass.enumValues(): Array diff --git a/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/APIController.jvm.kt b/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/APIController.jvm.kt new file mode 100644 index 00000000..1c53db76 --- /dev/null +++ b/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/APIController.jvm.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.ai.client.generativeai.common + +import io.ktor.client.engine.HttpClientEngine +import io.ktor.client.engine.okhttp.OkHttp + +internal actual fun createHttpClient(): HttpClientEngine = OkHttp.create() diff --git a/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/kotlin.jvm.kt b/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/kotlin.jvm.kt new file mode 100644 index 00000000..59b398eb --- /dev/null +++ b/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/kotlin.jvm.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.ai.client.generativeai.common.util + +import kotlin.reflect.KClass + +internal actual inline fun KClass.name(): String = java.name diff --git a/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/logging.jvm.kt b/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/logging.jvm.kt new file mode 100644 index 00000000..6590c6d3 --- /dev/null +++ b/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/logging.jvm.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.ai.client.generativeai.common.util + +internal actual fun Error(tag: String, message: String) { + System.err.println("[$tag]: $message") +} + +internal actual fun Warning(tag: String, message: String) { + println("[$tag]: $message") +} diff --git a/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/serialization.jvm.kt b/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/serialization.jvm.kt new file mode 100644 index 00000000..7edf1435 --- /dev/null +++ b/common/src/jvmMain/kotlin/com/google/ai/client/generativeai/common/util/serialization.jvm.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.ai.client.generativeai.common.util + +import com.google.ai.client.generativeai.common.SerializationException +import java.lang.reflect.Field +import kotlin.reflect.KClass +import kotlinx.serialization.SerialName + +/** + * A variant of [getAnnotation][Field.getAnnotation] that provides implicit Kotlin support. + * + * Syntax sugar for: + * ``` + * getAnnotation(T::class.java) + * ``` + */ +internal inline fun Field.getAnnotation() = getAnnotation(T::class.java) + +/** + * Provides the name to be used in serialization for this enum value. + * + * By default an enum is serialized to its [name][Enum.name], and can be overwritten by providing a + * [SerialName] annotation. + */ +internal actual fun > T.serialName(): String = + declaringJavaClass.getField(name).getAnnotation()?.value ?: name + +/** + * Variant of [kotlin.enumValues] that provides support for [KClass] instances of enums. + * + * @throws SerializationException if the class is not a valid enum. Beyond runtime emily magic, this + * shouldn't really be possible. + */ +internal actual fun > KClass.enumValues(): Array = + java.enumConstants ?: throw SerializationException("$simpleName is not a valid enum type.") diff --git a/common/src/test/java/com/google/ai/client/generativeai/common/APIControllerTests.kt b/common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/APIControllerTests.kt similarity index 98% rename from common/src/test/java/com/google/ai/client/generativeai/common/APIControllerTests.kt rename to common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/APIControllerTests.kt index e0f8bb71..c4fa5e2e 100644 --- a/common/src/test/java/com/google/ai/client/generativeai/common/APIControllerTests.kt +++ b/common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/APIControllerTests.kt @@ -94,8 +94,8 @@ internal class RequestFormatTests { "gemini-pro-1.0", RequestOptions(), mockEngine, - "genai-android/${BuildConfig.VERSION_NAME}", - null + "genai-android/1.0.0", + null, ) withTimeout(5.seconds) { @@ -122,7 +122,7 @@ internal class RequestFormatTests { RequestOptions(endpoint = "https://my.custom.endpoint"), mockEngine, TEST_CLIENT_ID, - null + null, ) withTimeout(5.seconds) { @@ -149,7 +149,7 @@ internal class RequestFormatTests { RequestOptions(), mockEngine, TEST_CLIENT_ID, - null + null, ) withTimeout(5.seconds) { @@ -179,7 +179,7 @@ internal class RequestFormatTests { RequestOptions(), mockEngine, TEST_CLIENT_ID, - null + null, ) withTimeout(5.seconds) { controller.countTokens(textCountTokenRequest("cats")) } @@ -203,7 +203,7 @@ internal class RequestFormatTests { RequestOptions(), mockEngine, TEST_CLIENT_ID, - null + null, ) withTimeout(5.seconds) { controller.countTokens(textCountTokenRequest("cats")) } @@ -226,7 +226,7 @@ internal class RequestFormatTests { RequestOptions(), mockEngine, TEST_CLIENT_ID, - null + null, ) withTimeout(5.seconds) { @@ -239,7 +239,7 @@ internal class RequestFormatTests { ToolConfig( functionCallingConfig = FunctionCallingConfig(mode = FunctionCallingConfig.Mode.AUTO) - ) + ), ) ) .collect { channel.close() } @@ -273,7 +273,7 @@ internal class RequestFormatTests { RequestOptions(), mockEngine, TEST_CLIENT_ID, - testHeaderProvider + testHeaderProvider, ) withTimeout(5.seconds) { controller.countTokens(textCountTokenRequest("cats")) } @@ -307,7 +307,7 @@ internal class RequestFormatTests { RequestOptions(), mockEngine, TEST_CLIENT_ID, - testHeaderProvider + testHeaderProvider, ) withTimeout(5.seconds) { controller.countTokens(textCountTokenRequest("cats")) } @@ -333,7 +333,7 @@ internal class ModelNamingTests(private val modelName: String, private val actua RequestOptions(), mockEngine, TEST_CLIENT_ID, - null + null, ) withTimeout(5.seconds) { @@ -363,7 +363,7 @@ internal class ModelNamingTests(private val modelName: String, private val actua fun textGenerateContentRequest(prompt: String) = GenerateContentRequest( model = "unused", - contents = listOf(Content(parts = listOf(TextPart(prompt)))) + contents = listOf(Content(parts = listOf(TextPart(prompt)))), ) fun textCountTokenRequest(prompt: String) = diff --git a/common/src/test/java/com/google/ai/client/generativeai/common/StreamingSnapshotTests.kt b/common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/StreamingSnapshotTests.kt similarity index 100% rename from common/src/test/java/com/google/ai/client/generativeai/common/StreamingSnapshotTests.kt rename to common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/StreamingSnapshotTests.kt diff --git a/common/src/test/java/com/google/ai/client/generativeai/common/UnarySnapshotTests.kt b/common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/UnarySnapshotTests.kt similarity index 100% rename from common/src/test/java/com/google/ai/client/generativeai/common/UnarySnapshotTests.kt rename to common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/UnarySnapshotTests.kt diff --git a/common/src/test/java/com/google/ai/client/generativeai/common/util/kotlin.kt b/common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/util/kotlin.kt similarity index 100% rename from common/src/test/java/com/google/ai/client/generativeai/common/util/kotlin.kt rename to common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/util/kotlin.kt diff --git a/common/src/test/java/com/google/ai/client/generativeai/common/util/tests.kt b/common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/util/tests.kt similarity index 97% rename from common/src/test/java/com/google/ai/client/generativeai/common/util/tests.kt rename to common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/util/tests.kt index 4adee54c..0064a9a5 100644 --- a/common/src/test/java/com/google/ai/client/generativeai/common/util/tests.kt +++ b/common/src/jvmTest/kotlin/com/google/ai/client/generativeai/common/util/tests.kt @@ -100,7 +100,7 @@ internal typealias CommonTest = suspend CommonTestScope.() -> Unit internal fun commonTest( status: HttpStatusCode = HttpStatusCode.OK, requestOptions: RequestOptions = RequestOptions(), - block: CommonTest + block: CommonTest, ) = doBlocking { val channel = ByteChannel(autoFlush = true) val mockEngine = MockEngine { @@ -113,7 +113,7 @@ internal fun commonTest( requestOptions, mockEngine, TEST_CLIENT_ID, - null + null, ) CommonTestScope(channel, apiController).block() } @@ -132,7 +132,7 @@ internal fun commonTest( internal fun goldenStreamingFile( name: String, httpStatusCode: HttpStatusCode = HttpStatusCode.OK, - block: CommonTest + block: CommonTest, ) = doBlocking { val goldenFile = loadGoldenFile("streaming/$name") val messages = goldenFile.readLines().filter { it.isNotBlank() } @@ -162,7 +162,7 @@ internal fun goldenStreamingFile( internal fun goldenUnaryFile( name: String, httpStatusCode: HttpStatusCode = HttpStatusCode.OK, - block: CommonTest + block: CommonTest, ) = commonTest(httpStatusCode) { val goldenFile = loadGoldenFile("unary/$name") @@ -183,4 +183,4 @@ internal fun goldenUnaryFile( internal fun loadGoldenFile(path: String): File = loadResourceFile("golden-files/$path") /** Loads a file from the test resources directory. */ -internal fun loadResourceFile(path: String) = File("src/test/resources/$path") +internal fun loadResourceFile(path: String) = File("src/jvmTest/resources/$path") diff --git a/common/src/test/resources/golden-files/streaming/failure-api-key.txt b/common/src/jvmTest/resources/golden-files/streaming/failure-api-key.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/failure-api-key.txt rename to common/src/jvmTest/resources/golden-files/streaming/failure-api-key.txt diff --git a/common/src/test/resources/golden-files/streaming/failure-empty-content.txt b/common/src/jvmTest/resources/golden-files/streaming/failure-empty-content.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/failure-empty-content.txt rename to common/src/jvmTest/resources/golden-files/streaming/failure-empty-content.txt diff --git a/common/src/test/resources/golden-files/streaming/failure-finish-reason-safety.txt b/common/src/jvmTest/resources/golden-files/streaming/failure-finish-reason-safety.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/failure-finish-reason-safety.txt rename to common/src/jvmTest/resources/golden-files/streaming/failure-finish-reason-safety.txt diff --git a/common/src/test/resources/golden-files/streaming/failure-http-error.txt b/common/src/jvmTest/resources/golden-files/streaming/failure-http-error.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/failure-http-error.txt rename to common/src/jvmTest/resources/golden-files/streaming/failure-http-error.txt diff --git a/common/src/test/resources/golden-files/streaming/failure-image-rejected.txt b/common/src/jvmTest/resources/golden-files/streaming/failure-image-rejected.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/failure-image-rejected.txt rename to common/src/jvmTest/resources/golden-files/streaming/failure-image-rejected.txt diff --git a/common/src/test/resources/golden-files/streaming/failure-prompt-blocked-safety.txt b/common/src/jvmTest/resources/golden-files/streaming/failure-prompt-blocked-safety.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/failure-prompt-blocked-safety.txt rename to common/src/jvmTest/resources/golden-files/streaming/failure-prompt-blocked-safety.txt diff --git a/common/src/test/resources/golden-files/streaming/failure-recitation-no-content.txt b/common/src/jvmTest/resources/golden-files/streaming/failure-recitation-no-content.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/failure-recitation-no-content.txt rename to common/src/jvmTest/resources/golden-files/streaming/failure-recitation-no-content.txt diff --git a/common/src/test/resources/golden-files/streaming/failure-unknown-model.txt b/common/src/jvmTest/resources/golden-files/streaming/failure-unknown-model.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/failure-unknown-model.txt rename to common/src/jvmTest/resources/golden-files/streaming/failure-unknown-model.txt diff --git a/common/src/test/resources/golden-files/streaming/success-basic-reply-long.txt b/common/src/jvmTest/resources/golden-files/streaming/success-basic-reply-long.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/success-basic-reply-long.txt rename to common/src/jvmTest/resources/golden-files/streaming/success-basic-reply-long.txt diff --git a/common/src/test/resources/golden-files/streaming/success-basic-reply-short.txt b/common/src/jvmTest/resources/golden-files/streaming/success-basic-reply-short.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/success-basic-reply-short.txt rename to common/src/jvmTest/resources/golden-files/streaming/success-basic-reply-short.txt diff --git a/common/src/test/resources/golden-files/streaming/success-citations-altname.txt b/common/src/jvmTest/resources/golden-files/streaming/success-citations-altname.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/success-citations-altname.txt rename to common/src/jvmTest/resources/golden-files/streaming/success-citations-altname.txt diff --git a/common/src/test/resources/golden-files/streaming/success-citations.txt b/common/src/jvmTest/resources/golden-files/streaming/success-citations.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/success-citations.txt rename to common/src/jvmTest/resources/golden-files/streaming/success-citations.txt diff --git a/common/src/test/resources/golden-files/streaming/success-quotes-escaped.txt b/common/src/jvmTest/resources/golden-files/streaming/success-quotes-escaped.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/success-quotes-escaped.txt rename to common/src/jvmTest/resources/golden-files/streaming/success-quotes-escaped.txt diff --git a/common/src/test/resources/golden-files/streaming/success-unknown-enum.txt b/common/src/jvmTest/resources/golden-files/streaming/success-unknown-enum.txt similarity index 100% rename from common/src/test/resources/golden-files/streaming/success-unknown-enum.txt rename to common/src/jvmTest/resources/golden-files/streaming/success-unknown-enum.txt diff --git a/common/src/test/resources/golden-files/unary/failure-api-key.json b/common/src/jvmTest/resources/golden-files/unary/failure-api-key.json similarity index 100% rename from common/src/test/resources/golden-files/unary/failure-api-key.json rename to common/src/jvmTest/resources/golden-files/unary/failure-api-key.json diff --git a/common/src/test/resources/golden-files/unary/failure-empty-content.json b/common/src/jvmTest/resources/golden-files/unary/failure-empty-content.json similarity index 100% rename from common/src/test/resources/golden-files/unary/failure-empty-content.json rename to common/src/jvmTest/resources/golden-files/unary/failure-empty-content.json diff --git a/common/src/test/resources/golden-files/unary/failure-finish-reason-safety.json b/common/src/jvmTest/resources/golden-files/unary/failure-finish-reason-safety.json similarity index 100% rename from common/src/test/resources/golden-files/unary/failure-finish-reason-safety.json rename to common/src/jvmTest/resources/golden-files/unary/failure-finish-reason-safety.json diff --git a/common/src/test/resources/golden-files/unary/failure-http-error.json b/common/src/jvmTest/resources/golden-files/unary/failure-http-error.json similarity index 100% rename from common/src/test/resources/golden-files/unary/failure-http-error.json rename to common/src/jvmTest/resources/golden-files/unary/failure-http-error.json diff --git a/common/src/test/resources/golden-files/unary/failure-image-rejected.json b/common/src/jvmTest/resources/golden-files/unary/failure-image-rejected.json similarity index 100% rename from common/src/test/resources/golden-files/unary/failure-image-rejected.json rename to common/src/jvmTest/resources/golden-files/unary/failure-image-rejected.json diff --git a/common/src/test/resources/golden-files/unary/failure-invalid-response.json b/common/src/jvmTest/resources/golden-files/unary/failure-invalid-response.json similarity index 100% rename from common/src/test/resources/golden-files/unary/failure-invalid-response.json rename to common/src/jvmTest/resources/golden-files/unary/failure-invalid-response.json diff --git a/common/src/test/resources/golden-files/unary/failure-malformed-content.json b/common/src/jvmTest/resources/golden-files/unary/failure-malformed-content.json similarity index 100% rename from common/src/test/resources/golden-files/unary/failure-malformed-content.json rename to common/src/jvmTest/resources/golden-files/unary/failure-malformed-content.json diff --git a/common/src/test/resources/golden-files/unary/failure-prompt-blocked-safety.json b/common/src/jvmTest/resources/golden-files/unary/failure-prompt-blocked-safety.json similarity index 100% rename from common/src/test/resources/golden-files/unary/failure-prompt-blocked-safety.json rename to common/src/jvmTest/resources/golden-files/unary/failure-prompt-blocked-safety.json diff --git a/common/src/test/resources/golden-files/unary/failure-quota-exceeded.json b/common/src/jvmTest/resources/golden-files/unary/failure-quota-exceeded.json similarity index 100% rename from common/src/test/resources/golden-files/unary/failure-quota-exceeded.json rename to common/src/jvmTest/resources/golden-files/unary/failure-quota-exceeded.json diff --git a/common/src/test/resources/golden-files/unary/failure-unknown-model.json b/common/src/jvmTest/resources/golden-files/unary/failure-unknown-model.json similarity index 100% rename from common/src/test/resources/golden-files/unary/failure-unknown-model.json rename to common/src/jvmTest/resources/golden-files/unary/failure-unknown-model.json diff --git a/common/src/test/resources/golden-files/unary/failure-unsupported-user-location.json b/common/src/jvmTest/resources/golden-files/unary/failure-unsupported-user-location.json similarity index 100% rename from common/src/test/resources/golden-files/unary/failure-unsupported-user-location.json rename to common/src/jvmTest/resources/golden-files/unary/failure-unsupported-user-location.json diff --git a/common/src/test/resources/golden-files/unary/success-basic-reply-long.json b/common/src/jvmTest/resources/golden-files/unary/success-basic-reply-long.json similarity index 100% rename from common/src/test/resources/golden-files/unary/success-basic-reply-long.json rename to common/src/jvmTest/resources/golden-files/unary/success-basic-reply-long.json diff --git a/common/src/test/resources/golden-files/unary/success-basic-reply-short.json b/common/src/jvmTest/resources/golden-files/unary/success-basic-reply-short.json similarity index 100% rename from common/src/test/resources/golden-files/unary/success-basic-reply-short.json rename to common/src/jvmTest/resources/golden-files/unary/success-basic-reply-short.json diff --git a/common/src/test/resources/golden-files/unary/success-citations-altname.json b/common/src/jvmTest/resources/golden-files/unary/success-citations-altname.json similarity index 100% rename from common/src/test/resources/golden-files/unary/success-citations-altname.json rename to common/src/jvmTest/resources/golden-files/unary/success-citations-altname.json diff --git a/common/src/test/resources/golden-files/unary/success-citations-nolicense.json b/common/src/jvmTest/resources/golden-files/unary/success-citations-nolicense.json similarity index 100% rename from common/src/test/resources/golden-files/unary/success-citations-nolicense.json rename to common/src/jvmTest/resources/golden-files/unary/success-citations-nolicense.json diff --git a/common/src/test/resources/golden-files/unary/success-citations.json b/common/src/jvmTest/resources/golden-files/unary/success-citations.json similarity index 100% rename from common/src/test/resources/golden-files/unary/success-citations.json rename to common/src/jvmTest/resources/golden-files/unary/success-citations.json diff --git a/common/src/test/resources/golden-files/unary/success-constraint-decoding-json.json b/common/src/jvmTest/resources/golden-files/unary/success-constraint-decoding-json.json similarity index 100% rename from common/src/test/resources/golden-files/unary/success-constraint-decoding-json.json rename to common/src/jvmTest/resources/golden-files/unary/success-constraint-decoding-json.json diff --git a/common/src/test/resources/golden-files/unary/success-including-severity.json b/common/src/jvmTest/resources/golden-files/unary/success-including-severity.json similarity index 100% rename from common/src/test/resources/golden-files/unary/success-including-severity.json rename to common/src/jvmTest/resources/golden-files/unary/success-including-severity.json diff --git a/common/src/test/resources/golden-files/unary/success-partial-usage-metadata.json b/common/src/jvmTest/resources/golden-files/unary/success-partial-usage-metadata.json similarity index 100% rename from common/src/test/resources/golden-files/unary/success-partial-usage-metadata.json rename to common/src/jvmTest/resources/golden-files/unary/success-partial-usage-metadata.json diff --git a/common/src/test/resources/golden-files/unary/success-quote-reply.json b/common/src/jvmTest/resources/golden-files/unary/success-quote-reply.json similarity index 100% rename from common/src/test/resources/golden-files/unary/success-quote-reply.json rename to common/src/jvmTest/resources/golden-files/unary/success-quote-reply.json diff --git a/common/src/test/resources/golden-files/unary/success-unknown-enum.json b/common/src/jvmTest/resources/golden-files/unary/success-unknown-enum.json similarity index 100% rename from common/src/test/resources/golden-files/unary/success-unknown-enum.json rename to common/src/jvmTest/resources/golden-files/unary/success-unknown-enum.json diff --git a/common/src/test/resources/golden-files/unary/success-usage-metadata.json b/common/src/jvmTest/resources/golden-files/unary/success-usage-metadata.json similarity index 100% rename from common/src/test/resources/golden-files/unary/success-usage-metadata.json rename to common/src/jvmTest/resources/golden-files/unary/success-usage-metadata.json diff --git a/generativeai/src/main/java/com/google/ai/client/generativeai/internal/util/conversions.kt b/generativeai/src/main/java/com/google/ai/client/generativeai/internal/util/conversions.kt index 95f8dde1..11eb1368 100644 --- a/generativeai/src/main/java/com/google/ai/client/generativeai/internal/util/conversions.kt +++ b/generativeai/src/main/java/com/google/ai/client/generativeai/internal/util/conversions.kt @@ -98,7 +98,7 @@ internal fun com.google.ai.client.generativeai.type.GenerationConfig.toInternal( candidateCount = candidateCount, maxOutputTokens = maxOutputTokens, stopSequences = stopSequences, - responseMimeType = responseMimeType + responseMimeType = responseMimeType, ) internal fun com.google.ai.client.generativeai.type.HarmCategory.toInternal() = @@ -203,10 +203,7 @@ internal fun Part.toPublic(): com.google.ai.client.generativeai.type.Part { functionResponse.response.toPublic(), ) is FileDataPart -> - com.google.ai.client.generativeai.type.FileDataPart( - fileData.fileUri, - fileData.mimeType, - ) + com.google.ai.client.generativeai.type.FileDataPart(fileData.fileUri, fileData.mimeType) else -> throw SerializationException( "Unsupported part type \"${javaClass.simpleName}\" provided. This model may not be supported by this SDK." @@ -274,7 +271,7 @@ internal fun GenerateContentResponse.toPublic() = com.google.ai.client.generativeai.type.GenerateContentResponse( candidates?.map { it.toPublic() }.orEmpty(), promptFeedback?.toPublic(), - usageMetadata?.toPublic() + usageMetadata?.toPublic(), ) internal fun CountTokensResponse.toPublic() = diff --git a/generativeai/src/main/java/com/google/ai/client/generativeai/type/Candidate.kt b/generativeai/src/main/java/com/google/ai/client/generativeai/type/Candidate.kt index 5d2724aa..1f63a734 100644 --- a/generativeai/src/main/java/com/google/ai/client/generativeai/type/Candidate.kt +++ b/generativeai/src/main/java/com/google/ai/client/generativeai/type/Candidate.kt @@ -25,7 +25,7 @@ internal constructor( val content: Content, val safetyRatings: List, val citationMetadata: List, - val finishReason: FinishReason? + val finishReason: FinishReason?, ) /** Rating for a particular [HarmCategory] with a provided [HarmProbability]. */ @@ -44,7 +44,7 @@ class CitationMetadata( val startIndex: Int = 0, val endIndex: Int, val uri: String, - val license: String? = null + val license: String? = null, ) /** The reason for content finishing. */ diff --git a/generativeai/src/main/java/com/google/ai/client/generativeai/type/GenerateContentResponse.kt b/generativeai/src/main/java/com/google/ai/client/generativeai/type/GenerateContentResponse.kt index ee4a701e..fad24fd6 100644 --- a/generativeai/src/main/java/com/google/ai/client/generativeai/type/GenerateContentResponse.kt +++ b/generativeai/src/main/java/com/google/ai/client/generativeai/type/GenerateContentResponse.kt @@ -28,7 +28,7 @@ import android.util.Log class GenerateContentResponse( val candidates: List, val promptFeedback: PromptFeedback?, - val usageMetadata: UsageMetadata? + val usageMetadata: UsageMetadata?, ) { /** Convenience field representing all the text parts in the response, if they exists. */ val text: String? by lazy { diff --git a/generativeai/src/main/java/com/google/ai/client/generativeai/type/GenerationConfig.kt b/generativeai/src/main/java/com/google/ai/client/generativeai/type/GenerationConfig.kt index e83e01ca..1ecd3924 100644 --- a/generativeai/src/main/java/com/google/ai/client/generativeai/type/GenerationConfig.kt +++ b/generativeai/src/main/java/com/google/ai/client/generativeai/type/GenerationConfig.kt @@ -37,7 +37,7 @@ private constructor( val candidateCount: Int?, val maxOutputTokens: Int?, val stopSequences: List?, - val responseMimeType: String? + val responseMimeType: String?, ) { class Builder { @@ -57,7 +57,7 @@ private constructor( candidateCount = candidateCount, maxOutputTokens = maxOutputTokens, stopSequences = stopSequences, - responseMimeType = responseMimeType + responseMimeType = responseMimeType, ) } diff --git a/generativeai/src/main/java/com/google/ai/client/generativeai/type/PromptFeedback.kt b/generativeai/src/main/java/com/google/ai/client/generativeai/type/PromptFeedback.kt index 7dc981a7..d03026a7 100644 --- a/generativeai/src/main/java/com/google/ai/client/generativeai/type/PromptFeedback.kt +++ b/generativeai/src/main/java/com/google/ai/client/generativeai/type/PromptFeedback.kt @@ -22,10 +22,7 @@ package com.google.ai.client.generativeai.type * @param blockReason The reason that content was blocked, if at all. * @param safetyRatings A list of relevant [SafetyRating]s. */ -class PromptFeedback( - val blockReason: BlockReason?, - val safetyRatings: List, -) +class PromptFeedback(val blockReason: BlockReason?, val safetyRatings: List) /** Describes why content was blocked. */ enum class BlockReason { diff --git a/generativeai/src/main/java/com/google/ai/client/generativeai/type/RequestOptions.kt b/generativeai/src/main/java/com/google/ai/client/generativeai/type/RequestOptions.kt index b12a5cbb..2c1c5f83 100644 --- a/generativeai/src/main/java/com/google/ai/client/generativeai/type/RequestOptions.kt +++ b/generativeai/src/main/java/com/google/ai/client/generativeai/type/RequestOptions.kt @@ -27,16 +27,10 @@ import kotlin.time.toDuration * first response. * @property apiVersion the api endpoint to call. */ -class RequestOptions( - val timeout: Duration, - val apiVersion: String = "v1beta", -) { +class RequestOptions(val timeout: Duration, val apiVersion: String = "v1beta") { @JvmOverloads constructor( timeout: Long? = Long.MAX_VALUE, apiVersion: String = "v1beta", - ) : this( - (timeout ?: Long.MAX_VALUE).toDuration(DurationUnit.MILLISECONDS), - apiVersion, - ) + ) : this((timeout ?: Long.MAX_VALUE).toDuration(DurationUnit.MILLISECONDS), apiVersion) } diff --git a/generativeai/src/main/java/com/google/ai/client/generativeai/type/Tool.kt b/generativeai/src/main/java/com/google/ai/client/generativeai/type/Tool.kt index 29cef4ec..42b8c287 100644 --- a/generativeai/src/main/java/com/google/ai/client/generativeai/type/Tool.kt +++ b/generativeai/src/main/java/com/google/ai/client/generativeai/type/Tool.kt @@ -22,6 +22,4 @@ package com.google.ai.client.generativeai.type * * @param functionDeclarations The set of functions that this tool allows the model access to */ -class Tool( - val functionDeclarations: List, -) +class Tool(val functionDeclarations: List) diff --git a/generativeai/src/main/java/com/google/ai/client/generativeai/type/UsageMetadata.kt b/generativeai/src/main/java/com/google/ai/client/generativeai/type/UsageMetadata.kt index ba1649e2..c051e1b2 100644 --- a/generativeai/src/main/java/com/google/ai/client/generativeai/type/UsageMetadata.kt +++ b/generativeai/src/main/java/com/google/ai/client/generativeai/type/UsageMetadata.kt @@ -26,5 +26,5 @@ package com.google.ai.client.generativeai.type class UsageMetadata( val promptTokenCount: Int, val candidatesTokenCount: Int, - val totalTokenCount: Int + val totalTokenCount: Int, ) diff --git a/generativeai/src/test/java/com/google/ai/client/generativeai/GenerateContentResponseTest.kt b/generativeai/src/test/java/com/google/ai/client/generativeai/GenerateContentResponseTest.kt index cab71e38..335e81d5 100644 --- a/generativeai/src/test/java/com/google/ai/client/generativeai/GenerateContentResponseTest.kt +++ b/generativeai/src/test/java/com/google/ai/client/generativeai/GenerateContentResponseTest.kt @@ -40,11 +40,11 @@ internal class GenerateContentResponseTest { }, listOf(), listOf(), - null + null, ) ), null, - null + null, ) response.functionCalls shouldHaveSize 2 @@ -64,11 +64,11 @@ internal class GenerateContentResponseTest { }, listOf(), listOf(), - null + null, ) ), null, - null + null, ) response.text shouldBe "This is a textPart" @@ -89,11 +89,11 @@ internal class GenerateContentResponseTest { }, listOf(), listOf(), - null + null, ) ), null, - null + null, ) response.text shouldBe "This is a textPart This is another textPart" diff --git a/generativeai/src/test/java/com/google/ai/client/generativeai/GenerativeModelTests.kt b/generativeai/src/test/java/com/google/ai/client/generativeai/GenerativeModelTests.kt index 286b4fd1..51501515 100644 --- a/generativeai/src/test/java/com/google/ai/client/generativeai/GenerativeModelTests.kt +++ b/generativeai/src/test/java/com/google/ai/client/generativeai/GenerativeModelTests.kt @@ -58,7 +58,7 @@ internal class GenerativeModelTests { mockApiController.generateContent( GenerateContentRequest_Common( "gemini-pro-1.0", - contents = listOf(Content_Common(parts = listOf(TextPart_Common("Why's the sky blue?")))) + contents = listOf(Content_Common(parts = listOf(TextPart_Common("Why's the sky blue?")))), ) ) } returns @@ -73,16 +73,11 @@ internal class GenerativeModelTests { safetyRatings = listOf(), citationMetadata = CitationMetadata_Common( - listOf( - CitationSources( - endIndex = 100, - uri = "http://www.example.com", - ) - ) - ) + listOf(CitationSources(endIndex = 100, uri = "http://www.example.com")) + ), ) ), - usageMetadata = UsageMetadata_Common(promptTokenCount = 10) + usageMetadata = UsageMetadata_Common(promptTokenCount = 10), ) val expectedResponse = @@ -97,14 +92,14 @@ internal class GenerativeModelTests { startIndex = 0, endIndex = 100, uri = "http://www.example.com", - license = null + license = null, ) ), - finishReason = null + finishReason = null, ) ), PromptFeedback(null, listOf()), - UsageMetadata(10, 0, 0 /* default to 0*/) + UsageMetadata(10, 0, 0 /* default to 0*/), ) val response = model.generateContent("Why's the sky blue?") @@ -114,7 +109,7 @@ internal class GenerativeModelTests { response.candidates[0].shouldBeEqualToUsingFields( expectedResponse.candidates[0], Candidate::finishReason, - Candidate::safetyRatings + Candidate::safetyRatings, ) response.candidates[0] .citationMetadata[0] @@ -134,7 +129,7 @@ internal class GenerativeModelTests { mockApiController.generateContent( GenerateContentRequest_Common( "gemini-pro-1.0", - contents = listOf(Content_Common(parts = listOf(TextPart_Common("Why's the sky blue?")))) + contents = listOf(Content_Common(parts = listOf(TextPart_Common("Why's the sky blue?")))), ) ) } throws InvalidAPIKeyException_Common("exception message") @@ -149,7 +144,7 @@ internal class GenerativeModelTests { mockApiController.generateContentStream( GenerateContentRequest_Common( "gemini-pro-1.0", - contents = listOf(Content_Common(parts = listOf(TextPart_Common("Why's the sky blue?")))) + contents = listOf(Content_Common(parts = listOf(TextPart_Common("Why's the sky blue?")))), ) ) } returns flow { throw UnsupportedUserLocationException_Common() } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 95644b24..461c3e99 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Nov 06 13:03:44 PST 2023 +#Tue May 21 10:49:10 CDT 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/plugins/build.gradle.kts b/plugins/build.gradle.kts index d0148a03..a7db5367 100644 --- a/plugins/build.gradle.kts +++ b/plugins/build.gradle.kts @@ -15,11 +15,11 @@ */ plugins { - `java-library` +// `java-library` `java-gradle-plugin` `kotlin-dsl` kotlin("jvm") version "1.8.22" - id("com.ncorti.ktfmt.gradle") version "0.16.0" + id("com.ncorti.ktfmt.gradle") version "0.18.0" id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.13.2" kotlin("plugin.serialization") version "1.8.22" } @@ -57,7 +57,7 @@ gradlePlugin { } dependencies { - implementation("com.android.tools.build:gradle:8.1.3") + implementation("com.android.tools.build:gradle:8.4.1") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.22") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0") implementation("org.jetbrains.kotlinx.binary-compatibility-validator:org.jetbrains.kotlinx.binary-compatibility-validator.gradle.plugin:0.13.2") diff --git a/plugins/src/main/java/com/google/gradle/plugins/ApiPlugin.kt b/plugins/src/main/java/com/google/gradle/plugins/ApiPlugin.kt index d94442f3..011347a3 100644 --- a/plugins/src/main/java/com/google/gradle/plugins/ApiPlugin.kt +++ b/plugins/src/main/java/com/google/gradle/plugins/ApiPlugin.kt @@ -17,11 +17,10 @@ package com.google.gradle.plugins import com.google.gradle.tasks.CopyFileTask -import com.google.gradle.util.android import com.google.gradle.util.apply import com.google.gradle.util.file +import com.google.gradle.util.getReleaseClasses import com.google.gradle.util.regularOutputFile -import com.google.gradle.util.release import com.google.gradle.util.tempFile import kotlinx.validation.KotlinApiBuildTask import org.gradle.api.Plugin @@ -61,7 +60,7 @@ abstract class ApiPlugin : Plugin { private fun Project.registerBuildApiTask() = tasks.register("buildApi") { - val classes = provider { android.release.output.classesDirs } + val classes = provider { getReleaseClasses() } inputClassesDirs = files(classes) inputDependencies = files(classes) diff --git a/plugins/src/main/java/com/google/gradle/util/gradle.kt b/plugins/src/main/java/com/google/gradle/util/gradle.kt index ba246f75..84885358 100644 --- a/plugins/src/main/java/com/google/gradle/util/gradle.kt +++ b/plugins/src/main/java/com/google/gradle/util/gradle.kt @@ -16,6 +16,7 @@ package com.google.gradle.util +import com.android.build.api.dsl.KotlinMultiplatformAndroidExtension import com.google.gradle.types.ModuleVersion import java.io.File import org.gradle.api.DefaultTask @@ -29,11 +30,14 @@ import org.gradle.api.provider.Provider import org.gradle.api.tasks.StopActionException import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.findByType import org.gradle.kotlin.dsl.getByType import org.gradle.workers.WorkAction import org.gradle.workers.WorkParameters import org.gradle.workers.WorkQueue import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation import org.jetbrains.kotlin.gradle.utils.provider @@ -153,17 +157,19 @@ fun List>.asSingleProvider(): Provider> { } } -/** The Android extension specific for Kotlin projects within Gradle. */ -val Project.android: KotlinAndroidProjectExtension - get() = extensions.getByType() +fun Project.getReleaseClasses(): FileCollection { + val android = extensions.findByType() + if(android !== null) { + return android.target.compilations.getByName("release").output.classesDirs + } -/** - * The `"release"` compilation target of a Kotlin Android project. - * - * In non android projects, this would be referred to as the main source set. - */ -val KotlinAndroidProjectExtension.release: KotlinJvmAndroidCompilation - get() = target.compilations.getByName("release") + val kmp = extensions.findByType() + if(kmp !== null) { + return kmp.targets.getByName("android").compilations.getByName("main").output.classesDirs + } + + throw RuntimeException("TODO() I shouldn't exist") +} /** * Provides a project property as the specified type, or null otherwise. diff --git a/settings.gradle.kts b/settings.gradle.kts index 3f4e53af..189e8ab8 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,6 +20,7 @@ pluginManagement { mavenCentral() gradlePluginPortal() } + includeBuild("./plugins") } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) @@ -32,4 +33,4 @@ dependencyResolutionManagement { rootProject.name = "generativeai" include(":generativeai") include(":common") -includeBuild("./plugins") + From 94a056155f22608e2181c1296535e61ad6a716e7 Mon Sep 17 00:00:00 2001 From: Daymon Date: Tue, 28 May 2024 13:07:03 -0500 Subject: [PATCH 2/2] Clean up util changes --- .../main/java/com/google/gradle/util/gradle.kt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/src/main/java/com/google/gradle/util/gradle.kt b/plugins/src/main/java/com/google/gradle/util/gradle.kt index 84885358..2bc4331b 100644 --- a/plugins/src/main/java/com/google/gradle/util/gradle.kt +++ b/plugins/src/main/java/com/google/gradle/util/gradle.kt @@ -157,18 +157,19 @@ fun List>.asSingleProvider(): Provider> { } } +/** + * TODO() + */ fun Project.getReleaseClasses(): FileCollection { - val android = extensions.findByType() - if(android !== null) { - return android.target.compilations.getByName("release").output.classesDirs + extensions.findByType()?.let { + return it.target.compilations.getByName("release").output.classesDirs } - val kmp = extensions.findByType() - if(kmp !== null) { - return kmp.targets.getByName("android").compilations.getByName("main").output.classesDirs + extensions.findByType()?.let { + return it.targets.getByName("android").compilations.getByName("main").output.classesDirs } - throw RuntimeException("TODO() I shouldn't exist") + throw RuntimeException("Library is missing an Android or KMP plugin") } /**