plugins { alias(libs.plugins.kotlin.multiplatform) apply false alias(libs.plugins.kotlin.jvm) apply false alias(libs.plugins.kotlin.serialization) apply false // maven-publish — стандартный плагин Gradle, объявлен apply'ем в subprojects ниже. } group = "pw.binom.agentik" // projectVersion определяется ниже как val, чтобы subprojects могли его // прочитать через rootProject.extra["projectVersion"]. // Publication version: -Pversion= (CICD publishes by release tag) с // fallback в gradle.properties (ключ `agentik.version.default`, не `version` // — иначе Gradle-мерж gradle.properties и -Pversion= отдаёт приоритет // gradle.properties). Без версии maven-publish падает с // "Invalid publication 'kotlinMultiplatform': version cannot be empty" — // это известный gotcha: subprojects читают rootProject.version ДО того, как // if-блок ниже успевает его установить. Фикс: provider+orElse вычисляется // eagerly, и subprojects получают готовую строку. val projectVersion: String = providers.gradleProperty("version") .map { it.trimStart('v', 'V') } // strip optional "v" prefix from tag .getOrElse(providers.gradleProperty("agentik.version.default").orElse("0.1.0-SNAPSHOT").get()) version = projectVersion extra["projectVersion"] = projectVersion // Home Nexus URL/creds — передаются через -Pbinom.repo.* из CI/CD workflow // (.gitea/workflows/release.yml). Локально для дебага: // ./gradlew publish -Pbinom.repo.url=http://... -Pbinom.repo.user=... -Pbinom.repo.password=... // Без -P URL падает на дефолтный placeholder (заглушка для локальной разработки). val binomRepoUrl = (findProperty("binom.repo.url") as String? ?: "http://nexus.xx/repository/caffeine/").toString() val binomRepoUser = (findProperty("binom.repo.user") as String? ?: "").toString() val binomRepoPassword = (findProperty("binom.repo.password") as String? ?: "").toString() // Per-module POM description. Один источник истины — карта ниже, // лишнее в settings.gradle.kts держим в комментарии-зеркале. // При добавлении нового модуля — добавь строку сюда + README.md в его корень. // Кладём в rootProject.extra ДО apply KMP-плагина в subprojects (beforeEvaluate // срабатывает позже, чем apply плагина, поэтому просто положить extra в // beforeEvaluate — поздно). val moduleDescriptions: Map = mapOf( "proto" to "agentik :proto — stateful KMP protocol (Agent/Conversation/Message/Event) replacing AG-UI; типы и контракт без сетевой логики.", "content-api" to "agentik :content-api — общие типы содержимого сообщения (Content/MessageContext/MessageOrigin/TurnTokens) для :proto, :journal-api, :outbox-api.", "outbox-api" to "agentik :outbox-api — durable (Event) и live-only (OnlineEvent) потоки событий диалога + OutboxStore/OnlineOutbox.", "skills" to "agentik :skills — парсер opencode-style SKILL.md / *.yaml (YAML-frontmatter + markdown body); загружается в system prompt.", "server" to "agentik :server — Ktor-фасад, экспонирующий Agent по HTTP+JSON+SSE под путём /agentik.", "client" to "agentik :client — Ktor-клиент (HTTP+JSON+SSE), превращающий /agentik в Agent/Conversation из :proto.", "memory-api" to "agentik :memory-api — интерфейсы долговременной памяти (MemoryStore, MemoryCategory, MemoryNote).", "memory-md" to "agentik :memory-md — Hermes-style реализация памяти поверх §-файлов (user/world/preference.md).", "memory-vector" to "agentik :memory-vector — ANN+JVector+SQLite реализация памяти с эмбеддингами (HTTP/SIGLIP).", "storage-core" to "agentik :storage-core — интерфейсы хранилища (MessageStore/WorkingMemoryStore/ConversationStore/ReflectionStore).", "storage-inmemory" to "agentik :storage-inmemory — исторический модуль (deleted 2026-09-22; in-memory реализации теперь живут в :journal-inmemory / :reflection-inmemory).", "storage-sqlite" to "agentik :storage-sqlite — исторический модуль (deleted 2026-09-22; ksqlite-реализации теперь живут в :journal-ksqlite / :context-ksqlite / :reflection-ksqlite).", "agent-toolsets" to "agentik :agent-toolsets — реестр инструментов + диспетчер тулов (enable_toolset/disable_toolset); переиспользуемое ядро.", "agentik-cli" to "agentik :agentik-cli — JVM CLI-клиент (JLine) к /agentik: REPL + slash-команды + стрим SSE.", // "agentik-tui" to "agentik :agentik-tui — Compose-for-Mosaic TUI-клиент (отключён 2026-09-17)." "standalone" to "agentik :standalone — single-jar HTTP-сервер со всеми транспортами (AG-UI/A2A/:proto), SQLite, памятью, скилами и SOUL.", ) rootProject.extra.set("moduleDescriptions", moduleDescriptions) subprojects { group = rootProject.group // KMP-плагин читает project.version на ранней стадии evaluation — ДО того // как сработает внешний subprojects-блок. Если version ещё "unspecified", // publication 'kotlinMultiplatform' создаётся с пустой version, и тогда // maven-publish падает с 'InvalidMavenPublicationException: version cannot // be empty'. Поэтому: // 1) eagerly переопределяем version в rootProject.extra (см. выше) // 2) на КАЖДЫЙ subproject вешаем beforeEvaluate, который выставляет // version до того, как KMP-плагин начнёт создавать publications. // per-module POM description берётся из rootProject.extra["moduleDescriptions"] // (см. корень build.gradle.kts); добавлять новый модуль — туда + README.md. // beforeEvaluate срабатывает ДО apply плагинов в build.gradle.kts модуля, так // что version/description уже валидны, когда KMP-плагин начинает создавать // publications. beforeEvaluate { description = (rootProject.extra["moduleDescriptions"] as Map)[project.name] ?: "agentik module: ${project.name}" version = rootProject.extra["projectVersion"] as String } apply(plugin = "maven-publish") extensions.configure("publishing") { repositories { maven { name = "caffeine" url = uri(binomRepoUrl) isAllowInsecureProtocol = true credentials { username = binomRepoUser password = binomRepoPassword } } } // Per-subproject POM-метаданные (name, scm, licenses, developers). // Также явно выставляем version/group для каждой публикации. В KMP-модулях // (особенно JVM-only с одним jvm() target) kotlin-multiplatform plugin // создаёт publication 'kotlinMultiplatform' на ранней стадии evaluation, // когда project.version ещё 'unspecified'. Простое присваивание // subprojects { version = ... } НЕ перезаписывает уже зафиксированную // version в publication → InvalidMavenPublicationException в CI. // Явная установка version здесь гарантирует, что публикация всегда // использует актуальное значение из rootProject.extra. publications.withType().configureEach { groupId = rootProject.group.toString() artifactId = project.name version = rootProject.extra["projectVersion"] as String pom { name = project.name description = (rootProject.extra["moduleDescriptions"] as? Map)?.get(project.name) ?: "agentik module: ${project.name}" url = "https://git.binom.pw/subochev/agentik" licenses { license { name = "Apache-2.0" url = "https://www.apache.org/licenses/LICENSE-2.0" } } developers { developer { id = "subochev" name = "Subochev Alexey" url = "https://git.binom.pw/subochev" } } scm { connection = "scm:git:https://git.binom.pw/subochev/agentik.git" developerConnection = "scm:git:ssh://git@git.binom.pw/subochev/agentik.git" url = "https://git.binom.pw/subochev/agentik" } } } } }