From f999e40556391e80fe845b9751e4e484633798a5 Mon Sep 17 00:00:00 2001 From: Lin Zhang Date: Tue, 21 Apr 2026 16:06:37 +0800 Subject: [PATCH 1/7] chore: upgrade Gradle and dependencies to latest stable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps AGP 9.0.1→9.1.1, Kotlin 2.3.10→2.3.20, Compose MP 1.10.1→1.10.3, Ktor 3.4.0→3.4.2, SQLDelight 2.2.1→2.3.2, GraalVM Native 0.11.4→1.0.0, Koog 0.6.3→0.8.0, Kermit 2.0.8→2.1.0, kotlinx-serialization 1.10.0→1.11.0, androidx-activity 1.12.4→1.13.0, androidx-core 1.17.0→1.18.0, androidx-lifecycle 2.9.6→2.10.0, dnssd 1.0.5→1.1.0, material3-adaptive alpha05→alpha06, Gradle wrapper 9.3.1→9.4.1. Koog 0.8.0 moved tools() from a package-level extension to a ToolRegistryBuilder member, so the now-obsolete `ai.koog.agents.core.tools.reflect.tools` imports are removed. --- .../ketch/ai/ResourceDiscoveryService.kt | 1 - gradle/libs.versions.toml | 28 +++++++++---------- gradle/wrapper/gradle-wrapper.properties | 2 +- .../com/linroid/ketch/mcp/KetchMcpServer.kt | 1 - 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/ai/discover/src/main/kotlin/com/linroid/ketch/ai/ResourceDiscoveryService.kt b/ai/discover/src/main/kotlin/com/linroid/ketch/ai/ResourceDiscoveryService.kt index ad283cbb..c3fe53fa 100644 --- a/ai/discover/src/main/kotlin/com/linroid/ketch/ai/ResourceDiscoveryService.kt +++ b/ai/discover/src/main/kotlin/com/linroid/ketch/ai/ResourceDiscoveryService.kt @@ -2,7 +2,6 @@ package com.linroid.ketch.ai import ai.koog.agents.core.agent.AIAgent import ai.koog.agents.core.tools.ToolRegistry -import ai.koog.agents.core.tools.reflect.tools import ai.koog.prompt.executor.clients.openai.OpenAIModels import ai.koog.prompt.executor.llms.all.simpleOpenAIExecutor import com.linroid.ketch.ai.agent.AgentOutputParser diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d67b968a..1571217a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,36 +1,36 @@ [versions] -agp = "9.0.1" +agp = "9.1.1" android-compileSdk = "36" android-minSdk = "26" android-targetSdk = "36" -androidx-activity = "1.12.4" +androidx-activity = "1.13.0" androidx-appcompat = "1.7.1" -androidx-core = "1.17.0" +androidx-core = "1.18.0" androidx-startup = "1.2.0" androidx-espresso = "3.7.0" -androidx-lifecycle = "2.9.6" +androidx-lifecycle = "2.10.0" androidx-testExt = "1.3.0" composeHotReload = "1.0.0" -composeMultiplatform = "1.10.1" -dnssd = "1.0.5" +composeMultiplatform = "1.10.3" +dnssd = "1.1.0" junit = "4.13.2" -kotlin = "2.3.10" +kotlin = "2.3.20" kotlinx-coroutines = "1.10.2" -kotlinx-serialization = "1.10.0" +kotlinx-serialization = "1.11.0" okio = "3.16.4" kotlinx-datetime = "0.7.1" -kermit = "2.0.8" -koog = "0.6.3" +kermit = "2.1.0" +koog = "0.8.0" libtorrent4j = "2.1.0-39" kotlinx-browser = "0.5.0" ktoml = "0.7.1" -ktor = "3.4.0" -sqldelight = "2.2.1" -graalvmNative = "0.11.4" +ktor = "3.4.2" +sqldelight = "2.3.2" +graalvmNative = "1.0.0" mavenPublish = "0.36.0" logback = "1.5.32" material3 = "1.10.0-alpha05" -material3-adaptive = "1.3.0-alpha05" +material3-adaptive = "1.3.0-alpha06" [libraries] dnssd = { module = "com.appstractive:dns-sd-kt", version.ref = "dnssd" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5f38436f..c82ad3ff 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/library/mcp/src/main/kotlin/com/linroid/ketch/mcp/KetchMcpServer.kt b/library/mcp/src/main/kotlin/com/linroid/ketch/mcp/KetchMcpServer.kt index dc730a8e..3924a9d4 100644 --- a/library/mcp/src/main/kotlin/com/linroid/ketch/mcp/KetchMcpServer.kt +++ b/library/mcp/src/main/kotlin/com/linroid/ketch/mcp/KetchMcpServer.kt @@ -1,7 +1,6 @@ package com.linroid.ketch.mcp import ai.koog.agents.core.tools.ToolRegistry -import ai.koog.agents.core.tools.reflect.tools import ai.koog.agents.mcp.server.startSseMcpServer import ai.koog.agents.mcp.server.startStdioMcpServer import com.linroid.ketch.api.KetchApi From d09d63241a287f9c09010e3076567dea303a6f4b Mon Sep 17 00:00:00 2001 From: Lin Zhang Date: Tue, 21 Apr 2026 17:28:07 +0800 Subject: [PATCH 2/7] ci: re-download iOS simulator runtime before iOS tests The macos-latest runner's iOS 26.2 simruntime is missing libswift_Concurrency.dylib, so test.kexe aborts on launch with "Library not loaded: @rpath/libswift_Concurrency.dylib". Running `xcodebuild -downloadPlatform iOS` re-fetches a complete runtime. See: https://github.com/actions/runner-images/issues/13853 --- .github/workflows/tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 13da4bc9..267c3c88 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -75,6 +75,9 @@ jobs: - uses: gradle/actions/setup-gradle@v5 + - name: Ensure iOS simulator runtime is complete + run: xcodebuild -downloadPlatform iOS + - name: Run iOS simulator tests run: ./gradlew iosSimulatorArm64Test From 3ba20280d9f711bd46562db90f09d6ad83cc3bf8 Mon Sep 17 00:00:00 2001 From: Lin Zhang Date: Wed, 20 May 2026 15:33:52 +0800 Subject: [PATCH 3/7] chore: upgrade Gradle, AGP, Kotlin, ktor, coroutines, Compose - Gradle 9.4.1 -> 9.5.1 - AGP 9.1.1 -> 9.2.1 (bumps android-compileSdk 36 -> 37 to satisfy androidx.compose.material3.adaptive:adaptive-android:1.3.0-alpha10 transitively required by material3-adaptive 1.3.0-alpha07) - Kotlin 2.3.20 -> 2.3.21 - ktor 3.4.2 -> 3.5.0 - kotlinx-coroutines 1.10.2 -> 1.11.0 - Compose Multiplatform 1.10.3 -> 1.11.0 - composeHotReload 1.0.0 -> 1.1.1 - graalvmNative 1.0.0 -> 1.1.0 - material3 1.10.0-alpha05 -> 1.11.0-alpha07 (aligned with compose 1.11.0) - material3-adaptive 1.3.0-alpha06 -> 1.3.0-alpha07 --- gradle/libs.versions.toml | 20 ++++++++++---------- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1571217a..a86b7731 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] -agp = "9.1.1" -android-compileSdk = "36" +agp = "9.2.1" +android-compileSdk = "37" android-minSdk = "26" android-targetSdk = "36" androidx-activity = "1.13.0" @@ -10,12 +10,12 @@ androidx-startup = "1.2.0" androidx-espresso = "3.7.0" androidx-lifecycle = "2.10.0" androidx-testExt = "1.3.0" -composeHotReload = "1.0.0" -composeMultiplatform = "1.10.3" +composeHotReload = "1.1.1" +composeMultiplatform = "1.11.0" dnssd = "1.1.0" junit = "4.13.2" -kotlin = "2.3.20" -kotlinx-coroutines = "1.10.2" +kotlin = "2.3.21" +kotlinx-coroutines = "1.11.0" kotlinx-serialization = "1.11.0" okio = "3.16.4" kotlinx-datetime = "0.7.1" @@ -24,13 +24,13 @@ koog = "0.8.0" libtorrent4j = "2.1.0-39" kotlinx-browser = "0.5.0" ktoml = "0.7.1" -ktor = "3.4.2" +ktor = "3.5.0" sqldelight = "2.3.2" -graalvmNative = "1.0.0" +graalvmNative = "1.1.0" mavenPublish = "0.36.0" logback = "1.5.32" -material3 = "1.10.0-alpha05" -material3-adaptive = "1.3.0-alpha06" +material3 = "1.11.0-alpha07" +material3-adaptive = "1.3.0-alpha07" [libraries] dnssd = { module = "com.appstractive:dns-sd-kt", version.ref = "dnssd" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c82ad3ff..317a32cf 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 24e4fb04bc0efbc39c9cd9ca2363f9b6b42e40c6 Mon Sep 17 00:00:00 2001 From: Lin Zhang Date: Wed, 20 May 2026 15:34:02 +0800 Subject: [PATCH 4/7] chore: rename androidLibrary { } to android { } for AGP 9.2 The androidLibrary { } DSL block is deprecated in AGP 9.2 in favor of android { }. Applied across all KMP modules consuming the com.android.kotlin.multiplatform.library plugin. --- app/shared/build.gradle.kts | 2 +- config/build.gradle.kts | 2 +- library/api/build.gradle.kts | 2 +- library/core/build.gradle.kts | 2 +- library/endpoints/build.gradle.kts | 2 +- library/ftp/build.gradle.kts | 2 +- library/kermit/build.gradle.kts | 2 +- library/ktor/build.gradle.kts | 2 +- library/remote/build.gradle.kts | 2 +- library/sqlite/build.gradle.kts | 2 +- library/torrent/build.gradle.kts | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/shared/build.gradle.kts b/app/shared/build.gradle.kts index 2dcb48fa..495c16f5 100644 --- a/app/shared/build.gradle.kts +++ b/app/shared/build.gradle.kts @@ -10,7 +10,7 @@ plugins { } kotlin { - androidLibrary { + android { namespace = "com.linroid.ketch.app.shared" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() diff --git a/config/build.gradle.kts b/config/build.gradle.kts index 515c0109..04a77e43 100644 --- a/config/build.gradle.kts +++ b/config/build.gradle.kts @@ -10,7 +10,7 @@ plugins { } kotlin { - androidLibrary { + android { namespace = "com.linroid.ketch.config" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() diff --git a/library/api/build.gradle.kts b/library/api/build.gradle.kts index 92295a10..ace17729 100644 --- a/library/api/build.gradle.kts +++ b/library/api/build.gradle.kts @@ -38,7 +38,7 @@ val generateVersion by tasks.registering { } kotlin { - androidLibrary { + android { namespace = "com.linroid.ketch.api" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() diff --git a/library/core/build.gradle.kts b/library/core/build.gradle.kts index 2c1e9c43..7142fdc2 100644 --- a/library/core/build.gradle.kts +++ b/library/core/build.gradle.kts @@ -20,7 +20,7 @@ kotlin { ) } - androidLibrary { + android { namespace = "com.linroid.ketch.core" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() diff --git a/library/endpoints/build.gradle.kts b/library/endpoints/build.gradle.kts index 9d7b0259..1aaeb462 100644 --- a/library/endpoints/build.gradle.kts +++ b/library/endpoints/build.gradle.kts @@ -11,7 +11,7 @@ plugins { } kotlin { - androidLibrary { + android { namespace = "com.linroid.ketch.endpoints" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() diff --git a/library/ftp/build.gradle.kts b/library/ftp/build.gradle.kts index 385b546d..0ce24343 100644 --- a/library/ftp/build.gradle.kts +++ b/library/ftp/build.gradle.kts @@ -12,7 +12,7 @@ plugins { } kotlin { - androidLibrary { + android { namespace = "com.linroid.ketch.ftp" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() diff --git a/library/kermit/build.gradle.kts b/library/kermit/build.gradle.kts index 91032aea..e7e5032c 100644 --- a/library/kermit/build.gradle.kts +++ b/library/kermit/build.gradle.kts @@ -10,7 +10,7 @@ plugins { } kotlin { - androidLibrary { + android { namespace = "com.linroid.ketch.kermit" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() diff --git a/library/ktor/build.gradle.kts b/library/ktor/build.gradle.kts index 3912019c..22d14618 100644 --- a/library/ktor/build.gradle.kts +++ b/library/ktor/build.gradle.kts @@ -10,7 +10,7 @@ plugins { } kotlin { - androidLibrary { + android { namespace = "com.linroid.ketch.ktor" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() diff --git a/library/remote/build.gradle.kts b/library/remote/build.gradle.kts index 171c7aa7..df1b928e 100644 --- a/library/remote/build.gradle.kts +++ b/library/remote/build.gradle.kts @@ -11,7 +11,7 @@ plugins { } kotlin { - androidLibrary { + android { namespace = "com.linroid.ketch.remote" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() diff --git a/library/sqlite/build.gradle.kts b/library/sqlite/build.gradle.kts index 0166a70a..9ee64af3 100644 --- a/library/sqlite/build.gradle.kts +++ b/library/sqlite/build.gradle.kts @@ -10,7 +10,7 @@ plugins { } kotlin { - androidLibrary { + android { namespace = "com.linroid.ketch.sqlite" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() diff --git a/library/torrent/build.gradle.kts b/library/torrent/build.gradle.kts index 92f0bc34..d34f49c8 100644 --- a/library/torrent/build.gradle.kts +++ b/library/torrent/build.gradle.kts @@ -11,7 +11,7 @@ plugins { } kotlin { - androidLibrary { + android { namespace = "com.linroid.ketch.torrent" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() From 87ba97dcb85ac6beb9add4769bab898db7a2a4dc Mon Sep 17 00:00:00 2001 From: Lin Zhang Date: Wed, 20 May 2026 15:59:22 +0800 Subject: [PATCH 5/7] fix(ios): bump iOS deployment target to 18.0 for app:shared Compose Multiplatform 1.11.0's compose-ui-uikit references UIViewLayoutRegion, an iOS 18-only Objective-C class. With Kotlin/Native's default deployment target of 14.0, the iosSimulatorArm64 link fails with 'Undefined symbols: _OBJC_CLASS_$_UIViewLayoutRegion'. The dnssd 1.1.0 cinterop is also built for iOS 15+, producing 'object file was built for newer iOS-simulator version (15.0) than being linked (14.0)' warnings. Locally the link succeeds but the test binary still references @rpath/libswift_Concurrency.dylib (back-deployment dylib for iOS <15), which iOS 26.5 simruntime no longer ships, causing test.kexe to abort with 'Library not loaded: @rpath/libswift_Concurrency.dylib'. Override osVersionMin for both iosArm64 and iosSimulatorArm64 to 18.0 via -Xoverride-konan-properties, applied to all KotlinNativeTarget compilations in this module. --- app/shared/build.gradle.kts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/shared/build.gradle.kts b/app/shared/build.gradle.kts index 495c16f5..9c350ede 100644 --- a/app/shared/build.gradle.kts +++ b/app/shared/build.gradle.kts @@ -1,5 +1,6 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget plugins { alias(libs.plugins.kotlinMultiplatform) @@ -30,6 +31,22 @@ kotlin { } } + // Compose Multiplatform 1.11+ references iOS 18 APIs (e.g. UIViewLayoutRegion in + // compose-ui-uikit) and dnssd 1.1.0 is built for iOS 15+. Kotlin/Native defaults to + // iOS 14.0, which causes link failures and missing back-deployment dylib lookups at + // runtime. Override the minimum iOS version to 18.0. + targets.withType().configureEach { + compilations.configureEach { + compileTaskProvider.configure { + compilerOptions.freeCompilerArgs.add( + "-Xoverride-konan-properties=" + + "osVersionMin.ios_arm64=18.0;" + + "osVersionMin.ios_simulator_arm64=18.0", + ) + } + } + } + jvm() @OptIn(ExperimentalWasmDsl::class) From 4223ca9d929121401db59c64dc7c43d7ccc439dc Mon Sep 17 00:00:00 2001 From: Lin Zhang Date: Wed, 20 May 2026 16:21:36 +0800 Subject: [PATCH 6/7] ci: switch iOS tests to macos-26 runner for Xcode 26 Compose Multiplatform 1.11.0's compose-ui-uikit references UIViewLayoutRegion, an iOS 26.0 API (API_AVAILABLE(ios(26.0))). The macos-latest (macos-15) runner ships Xcode 16.4 whose iOS 18 SDK does not expose this symbol, so the iosSimulatorArm64 link fails with 'Undefined symbols: _OBJC_CLASS_$_UIViewLayoutRegion' even after overriding the deployment target. macos-26 runner ships Xcode 26.2 (default) with iOS SDK 26, which has UIViewLayoutRegion, so the symbol resolves at link time. --- .github/workflows/tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 267c3c88..3019e316 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -64,7 +64,10 @@ jobs: ios-tests: name: iOS Tests - runs-on: macos-latest + # Use macos-26 for Xcode 26 (default 26.2) which ships the iOS 26 SDK. + # Compose Multiplatform 1.11+ references iOS 26 APIs (UIViewLayoutRegion) + # that are not present in the iOS 18 SDK bundled with Xcode 16.x. + runs-on: macos-26 steps: - uses: actions/checkout@v6 From 645ed66e589c7df2bb128c4dd9973482196512fd Mon Sep 17 00:00:00 2001 From: Lin Zhang Date: Wed, 20 May 2026 16:29:14 +0800 Subject: [PATCH 7/7] ci: drop xcodebuild -downloadPlatform step on macos-26 The step was a workaround for macos-15's broken iOS 26.2 sim runtime (missing libswift_Concurrency.dylib). macos-26 with Xcode 26.2 ships a complete iOS sim runtime by default. The command also fails with exit 70 on macos-26 (no installable platforms available), breaking the job. --- .github/workflows/tests.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3019e316..f08d7b9f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -78,9 +78,6 @@ jobs: - uses: gradle/actions/setup-gradle@v5 - - name: Ensure iOS simulator runtime is complete - run: xcodebuild -downloadPlatform iOS - - name: Run iOS simulator tests run: ./gradlew iosSimulatorArm64Test