d5e3f2dcef
Punkt 7 of NATIVE-COMPATIBILITY.md. Proto sources were already on
kotlin.time.Instant (migrated earlier); the kotlinx-datetime api dep
in :proto/build.gradle.kts and the implementation dep in
:standalone/build.gradle.kts were dead weight.
Dropped:
- api(libs.kotlinx.datetime) from proto/build.gradle.kts
- implementation(libs.kotlinx.datetime) from standalone/build.gradle.kts
- [versions] kotlinx-datetime and [libraries] kotlinx-datetime from
gradle/libs.versions.toml
Verification: ./gradlew :server:assemble (all 9 native targets) +
./gradlew :standalone:jvmTest (44/44 green, 0 failures) — both pass.
The kotlinx-datetime typealias was deprecated in 0.8.0 (memory #3708);
now nothing in agentik pulls the library.
11 KiB
11 KiB
Совместимость с native (linuxX64) — чеклист
Цель: :standalone собирается и запускается как linuxX64 executable (и потенциально
остальные нативные таргеты KMP). Текущее состояние — JVM-only executable на
runJvm-таске.
Формат: - N. [ ] — задача; - N. [x] — выполнена; - N. [-] — отменена/не нужна.
Решения (что выбрали и почему) — курсивом внизу пункта.
Блок 1. Подготовка (уже сделана или тривиальная)
-
- Замена
java.util.UUIDна KMP-stdlib (kotlin.uuid.Uuid). HelperIds.new(prefix)вstandalone/src/commonMain/.../persistence/Ids.kt, три call-site (ChatAgent,ChatConversation,SqliteWorkingMemoryStore). Коммитe816d8d.
- Замена
-
- HTTP-движок:
ktor-server-netty→ktor-server-cio. Netty — JVM-only; CIO — KMP (jvm + linuxX64 + ios/...). Каталог-эntry Netty оставлен вlibs.versions.tomlна случай отката. Коммитe816d8d.
- HTTP-движок:
Блок 2. Библиотеки litert-kmp (наши)
-
litert-api: добавитьlinuxX64()вkotlin{}. Сейчас толькоandroidTarget() + jvm(). commonMain уже KMP-ready (толькоkotlinx-coroutines-core). Объём: одна строка вlitert-api/build.gradle.kts, одинlitert-api-linuxx64-артефакт публикуется в Nexus.
-
litert-openai: добавитьlinuxX64()вkotlin{}. Та же история. commonMain deps (ktor-client-core,ktor-client-cio,kotlinx-serialization-json) — все KMP с готовыми linuxX64-артефактами. Объём: одна строка + проверить, что Android-only фичи (если есть) изолированы вandroidMain(сейчас модуль не имеетandroidMain-специфичного кода). Каталог-записьlitert-openai-jvm→ переименовать вlitert-openai(чтобы Linux-таргет подтягивал-linuxx64-вариант автоматически, не нужно ручногоwhen target).
-
- [-]
litert-google: linuxX64 — невозможно. Upstream-блокер: Google публикуетlitertlm-android(AAR с.so) иlitertlm-jvm(fat-jar с.soдля linux/mac/win JVM), но НЕ нативногоlitertlm-linuxx64. Без правки upstream LiteRT-LM KMP-враппер для linuxX64 не напишется. Варианты: (a) выкинутьlitert-googleна linuxX64 (backend=google→ отказ); (b) альтернативный движок (llama.cpp через JNI/Kotlin/Native); (c) upstream PR вlitertlm. Решение: (a) для v1 linuxX64 — упасть с понятной ошибкойLlmBackend.GOOGLE is not supported on this platformвместо reflection-fallback на JVM .so, который на linuxX64 не сработает бы.
- [-]
Блок 3. Наш :server модуль
-
- Переписать
:serverсkotlin("jvm")наkotlin("multiplatform"). Все 9 целей сборки (jvm + macosX64 + macosArm64 + iosX64 + iosArm64 + iosSimulatorArm64 + linuxX64 + linuxArm64 + mingwX64) собираются./gradlew :server:assembleбез ошибок. Блокеров нет: Ktorktor-server-{core,sse,cio,content-negotiation}иktor-io(дляByteWriteChannel.writeStringUtf8) есть в KMP-вариантах под все цели;kotlin.time.Instantуже использовался. Единственное изменение по сравнению с JVM-версией:respondTextWriter(JVM-only) →respondBytesWriter+writeStringUtf8(KMP, тот жеByteWriteChannelAPI). Источники переехалиsrc/main/kotlin/...→src/commonMain/kotlin/....:standalone:jvmTest44/44 зелёные после миграции.
- Переписать
Блок 4. Наш :proto модуль
-
:proto: убратьkotlinx-datetimeapi-dep, оставитьkotlin.time.Instant. Источник уже был наkotlin.time.Instant(мигрирован ранее), ноkotlinx-datetimeоставался в gradle как мёртваяapi-зависимость. Удалено:
api(libs.kotlinx.datetime)изproto/build.gradle.ktsimplementation(libs.kotlinx.datetime)изstandalone/build.gradle.kts[versions] kotlinx-datetimeи[libraries] kotlinx-datetimeизgradle/libs.versions.tomlkotlin.time.Instantдоступен во всех KMP-целях без opt-in../gradlew :server:assemble+:standalone:jvmTest44/44 — зелёные.
Блок 5. SQLDelight — нативный драйвер
-
sqlite-driver(JVM/JDBC) →native-driverдля linuxX64. В jvmMain: оставитьsqlite-driver(JDBC overjava.sql.DriverManager). В linuxX64Main: добавитьnative-driver— KMP driver поверх cinterop сlibsqlite3(нужен-lsqlite3linker-флаг илиSQLiteBundleизco.touchlab:sqliterдля бандлинга). СоздатьSqliteStores- нейтральный интерфейс хранилищ (он уже есть вcommonMain), разделитьjvmMain/SqliteStores.ktиlinuxX64Main/SqliteStoresNative.kt— оба реализуют одинcommonMain-интерфейс. Объём: ~150 строк (новыйSqliteStoresNative.kt+ gradle wiring). Решение по бандлу: использоватьSQLiteBundleизco.touchlab:sqliter(KMP-обёртка, тянет свой libsqlite) — без зависимости от системного libsqlite3, бинарь работает на любом linux.
-
- Тесты SQLite переписать на commonTest +
expect/actualобёртку.inMemory()-открытие вnative-driverиспользует другой API (нет JDBC:memory:). Объём: одинexpect fun openInMemory()в commonMain + дваactual(JDBCjdbc:sqlite::memory:/ native-driver нативный API).
- Тесты SQLite переписать на commonTest +
Блок 6. Внешние либы (a2a-server, agui-server) — наши
-
agui-server: проверить KMP-готовность. Per Memory #3561 — KMP jvm+native. Если по факту уже KMP — только подключитьlinuxX64-артефакт в:standalone; если JVM-only — пункт 11.
-
a2a-server: JVM-only → KMP. Per Memory #3561 — JVM-only (client/server; shared уже KMP). Без native-таргета весь стек A2A недоступен на linuxX64. Объём: переписать наmultiplatform, выделить engine-нейтральную маршрутизацию. Альтернатива: на linuxX64 не подключать a2a-server вообще (только:server-фасад). Решение отложено — зависит от того, нужен ли нативный MCP-юзер-кейс вообще подключаться к A2A.
Блок 7. :standalone — добавить native target
-
standalone/build.gradle.kts: добавитьlinuxX64()иlinuxX64Main/linuxX64Testsource-sets. ВlinuxX64Main::server(после п.6),litert-openai(после п.4),litert-api(после п.3),ktor-server-cio(engine),ktor-client-cio,kotlin-sdk-client(MCP — KMP, готов),kotlinx-io(KMP, готов). Исключитьlitert-google(п.5) иa2a-server(п.11) из linuxX64Main.
-
Main.kt: разделить наcommonMain(бизнес-логика: создание ChatAgent, MCP, LlmConfig) +jvmMain/linuxX64Main(выбор engine, embeddedServer). embeddedServer(CIO, …) — один и тот же код на обеих платформах, KMP-нейтрален. Главное отличие —SqliteStores.open()и обработка GOOGLE-бэкенда на linuxX64 (fail-fast).
Блок 8. Тесты и CI
-
linuxX64Testsource-set. Покрыть те же 44 теста на native: должен зелёный прогон через./gradlew :standalone:linuxX64Test. SQLDelight-тесты на native требуютlibsqlite3/SQLiteBundleна машине (CI-linux предоставляет).
-
- Smoke e2e на linuxX64. Запустить
./gradlew :standalone:runLinuxX64локально, проверитьPOST /agentik/conversations→ 201, цикл с реальным LLM через OpenAI backend; убедиться что LiteRT-LM GOOGLE не подключается (отказ с понятной ошибкой).
- Smoke e2e на linuxX64. Запустить
Блок 9. Дистрибуция native-бинаря
-
runLinuxX64-таска через KMP binaries DSL. После добавленияlinuxX64()KMP генерирует её автоматически — нужно только убедиться чтоbinaries { executable { mainClass.set("pw.binom.agentik.standalone.MainKt") } }работает для linuxX64 (по аналогии с уже настроеннымrunJvm).
-
- Дистрибутив
.tar/.zip/AppImage/Docker. KMPassembleDistдля linuxX64 делает tar.gz/zip. Для прод-дистрибуции — Docker-образ (FROM gcr.io/distroless/cc) или AppImage. Объём: ~50 строк Dockerfile + GitHub Action.
- Дистрибутив
Что НЕ блокирует linuxX64 (закрыто или тривиально)
kotlinx-coroutines-core— KMP linuxX64 ✓kotlinx-serialization-json— KMP linuxX64 ✓kotlinx-io— KMP linuxX64 (используется в MCP stdio-transport) ✓kotlin-sdk-client(MCP) — KMP full targets ✓ktor-server-core,ktor-server-sse,ktor-server-cio— KMP linuxX64 ✓ktor-client-core,ktor-client-cio— KMP linuxX64 ✓pw.binom.uuid— отсутствует в проекте (используемkotlin.uuid) ✓
Жёсткие блокеры (не обойти без upstream-работы)
litertlm-jvm→ нуженlitertlm-nativeот Google (см. п.5)a2a-serverJVM-only (см. п.11) — нужно переписать или явно не подключатьagui-serverKMP-готовность под вопросом (см. п.10)