Files
agentik/standalone/build.gradle.kts
T
subochev f5a551b2ae logging: kotlin-logging 3.0.5 + logback-classic + AGENTIK_LOG_LEVEL env
Заменил все System.err.println / println на структурное логирование
(kotlin-logging, пакет mu) — теперь логи идут с timestamp/level/thread/logger.

* gradle/libs.versions.toml: kotlin-logging = "3.0.5" (в прокси доступна
  только эта версия; новые 7.x пока не подтянуты), logback-classic = "1.5.18".
* standalone/build.gradle.kts: implementation(libs.kotlin.logging) +
  implementation(libs.logback.classic) в jvmMain.
* standalone/src/jvmMain/resources/logback.xml: консольный appender,
  pattern с timestamp/level/thread/logger, level управляется через
  ${AGENTIK_LOG_LEVEL:-INFO} (env override на старте JVM), уровни
  io.netty/ai.onnxruntime уведены в WARN чтобы не забивать канал.
* Заменены все System.err.println в: ChatConversation (14 callsites),
  Curator (2), McpRegistry (5), McpConfig (2), Main (2). Startup banner
  в Main оставлен на println — это user-facing output, не log.
* Tests: 288 зелёных (только замена log-вызовов, без изменения семантики).

Smoke: `04:53:49.313 INFO  [DefaultDispatcher-worker-4] p.b.a.s.agent.memory.Curator - started (interval=1d, maxAge=90d, maxUseCount=0)`
подтверждает структурный лог вместо println. AGENTIK_LOG_LEVEL=DEBUG работает.
2026-09-15 04:54:16 +03:00

162 lines
6.9 KiB
Kotlin
Raw 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.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.artifacts.ConfigurationContainer
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.sqldelight)
alias(libs.plugins.shadow)
}
kotlin {
jvmToolchain(21)
jvm {
binaries {
executable {
mainClass.set("pw.binom.agentik.standalone.MainKt")
}
}
}
sourceSets {
commonMain.dependencies {
implementation(project(":proto"))
implementation(project(":server"))
// Commons
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
// litert-kmp: контракт (commonMain)
api(libs.litert.api)
// SQLDelight runtime (commonMain)
api(libs.sqldelight.runtime)
api(libs.sqldelight.coroutines)
}
jvmMain.dependencies {
// Парсер и загрузчик скилов (YAML frontmatter + markdown body).
implementation(project(":skills"))
// Долговременная память (Hermes-style MD-бэкенд).
implementation(project(":memory-api"))
implementation(project(":memory-md"))
implementation(project(":memory-vector"))
// litert-openai: JVM-реализация
implementation(libs.litert.openai)
// litert-google: встроенный LiteRT-LM движок, нужен только на runtime
runtimeOnly(libs.litert.google)
// SQLDelight JDBC driver (JVM)
implementation(libs.sqldelight.sqlite.driver)
// 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)
implementation(libs.ktor.serialization.kotlinx.json)
// Логирование: 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.kotlin.test)
}
jvmTest.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)
}
}
}
sqldelight {
databases {
create("AgentikDatabase") {
packageName.set("pw.binom.agentik.standalone.persistence.sqlite")
srcDirs.setFrom("src/jvmMain/sqldelight")
}
}
}
// --- 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 org.gradle.api.artifacts.ConfigurationContainer
} catch (_: ClassCastException) {
// KGP-generated dependency accessor; обходим через raw project.
@Suppress("UNCHECKED_CAST")
(project as org.gradle.api.Project).configurations as org.gradle.api.artifacts.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
}