Files
agentik/standalone/build.gradle.kts
T

169 lines
8.1 KiB
Kotlin
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@file:OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class)
import org.gradle.api.artifacts.ConfigurationContainer
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.shadow)
}
// CI-флаг: при -PskipVectorMemory=true :memory-vector не подключается как
// зависимость — нужно для CI runner'а (text-embedding-kmp ещё не опубликован
// в caffeine). Подробнее см. memory-vector/build.gradle.kts.
val skipVectorMemory: Boolean =
(project.findProperty("skipVectorMemory") == "true") ||
System.getenv("SKIP_VECTOR_MEMORY") == "1"
// :standalone — единственный entry-point проекта, JVM-only по факту (один
// `jvm()` target). Чтобы не таскать лишние sourceSet'ы, ВСЁ живёт в
// commonMain + commonTest — даже зависимости, которые формально JVM-only
// (ktor-server-cio, litert-openai, storage-ksqlite, ...). KMP-плагин тут
// только ради бесшовного потребления KMP-зависимостей (`:proto`, `:server`,
// `:journal-api`, ...); компилируется всё ровно в одну JVM-таргет.
kotlin {
jvmToolchain(21)
jvm {
binaries {
executable {
mainClass.set("pw.binom.agentik.standalone.MainKt")
}
}
}
sourceSets {
commonMain.dependencies {
// Протокол + KMP storage API
implementation(project(":proto"))
implementation(project(":server"))
implementation(project(":journal-api"))
implementation(project(":outbox-api"))
implementation(project(":context-api"))
implementation(project(":reflection-api"))
// Commons
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
// Парсер и загрузчик скилов (YAML frontmatter + markdown body).
implementation(project(":skills"))
// Долговременная память (Hermes-style MD-бэкенд) + хранилище истории.
implementation(project(":memory-api"))
implementation(project(":memory-md"))
if (!skipVectorMemory) {
implementation(project(":memory-vector"))
}
// SQLite-бэкенд (ksqlite JNI) — JVM-only по факту.
implementation(project(":storage-ksqlite"))
// Bounded-tail live event stream + per-event TTL.
implementation(project(":outbox-inmemory"))
// LLM-toolsets + generic LLM-side tools (LlmReflector, SkillMiner,
// LlmMemoryReviewer, ContextCompactor, парсеры/промпты).
implementation(project(":agent-toolsets"))
implementation(project(":llm-tools"))
// Generic MCP-bridge (McpConfig, McpRegistry, McpLiteToolAdapter).
implementation(project(":mcp-bridge"))
// litert-kmp: контракт (commonMain)
api(libs.litert.api)
// litert-openai: JVM-реализация
implementation(libs.litert.openai)
// litert-google: встроенный LiteRT-LM движок, нужен только на runtime
runtimeOnly(libs.litert.google)
// Ktor server (для :server facade + a2aServer)
// Используем CIO вместо Netty — он KMP (jvm + linuxX64/ios/...), нам нужен
// для будущей native-сборки; на JVM работает идентично для нашего сценария.
implementation(libs.ktor.server.core)
implementation(libs.ktor.server.sse)
implementation(libs.ktor.server.cio)
implementation(libs.ktor.server.content.negotiation)
implementation(libs.ktor.serialization.kotlinx.json)
// Транспортные фасады (A2A остаётся заготовкой; на v1 не подключается в Main.kt —
// см. docs/ARCHITECTURE.md §3).
implementation(libs.a2a.server)
// MCP (Model Context Protocol) клиент — подключение внешних/внутренних MCP-серверов
implementation(libs.mcp.sdk.client)
implementation(libs.ktor.client.core)
implementation(libs.ktor.client.cio)
implementation(libs.ktor.client.content.negotiation)
// Логирование: kotlin-logging (тонкая обёртка slf4j-api) + logback-classic
// (binding для JVM; без него slf4j-api NOP-логирует и не падает).
implementation(libs.kotlin.logging)
implementation(libs.logback.classic)
}
commonTest.dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
implementation(libs.kotlin.test)
// Ktor test engine для smoke-тестов HTTP
implementation(libs.ktor.server.test.host)
}
}
}
// --- Fatjar (uberjar) ---
//
// :standalone — KMP jvm-only бэкенд. Стандартный KMP `jvmJar` содержит только
// наши классы и требует подтянуть все зависимости на runtime через classpath.
// Для дистрибутива нужен self-contained `*-all.jar`, который содержит и наш
// код, и runtime classpath. Делается это Shadow-плагином:
//
// 1. shadowJar расширяет `jvmJar` (через from(tasks.named("jvmJar")))
// 2. Добавляет все артефакты из jvmRuntimeClasspath как `zipTree`
// 3. Корректно сливает META-INF/services (через ServiceFileTransformer)
// 4. Прописывает Main-Class в манифесте
//
// Результат: `build/libs/standalone-*-all.jar` запускается как
// java -jar standalone-0.1.0-all.jar
//
// KMP-сборка под ios/lin/macos не затрагивается — задача живёт только в jvm.
// Shadow 8.x не авторегистрирует shadowJar в KMP-проектах (нет стандартного `jar`),
// поэтому регистрируем явно через tasks.register.
//
// В Gradle 9 KGP подменяет `configurations` на сгенерированный dependency-accessor
// (он возвращает List), поэтому используем прямой доступ к Project API.
val shadowJarTask = tasks.register<ShadowJar>("shadowJar") {
archiveBaseName.set("standalone")
archiveClassifier.set("all")
description = "Self-contained fatjar with all runtime dependencies bundled."
group = "build"
from(tasks.named("jvmJar"))
// javaClass-каст через Any? чтобы вытащить реальный ConfigurationContainer
// из любого типа, который сейчас прикидывается `configurations`.
val cc = try {
@Suppress("UNCHECKED_CAST")
configurations as ConfigurationContainer
} catch (_: ClassCastException) {
// KGP-generated dependency accessor; обходим через raw project.
@Suppress("UNCHECKED_CAST")
(project as org.gradle.api.Project).configurations as ConfigurationContainer
}
from(cc.getByName("jvmRuntimeClasspath"))
mergeServiceFiles()
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes["Main-Class"] = "pw.binom.agentik.standalone.MainKt"
attributes["Implementation-Title"] = "agentik-standalone"
attributes["Implementation-Version"] = project.version.toString()
}
includeEmptyDirs = false
}