- README.md в каждом подмодуле: для библиотек — описание проблемы, подключение через maven-central/caffeine, версии в gradle/libs.versions.toml. Для запускаемых модулей — команды запуска + переменные среды с дефолтами. - Корневой README.md переписан как навигационный хаб: что это, где клиенты, где серверы, как собрать, как опубликовать. - build.gradle.kts: per-module POM-description через единую карту в rootProject.extra (порядок важен — нужно ДО apply плагина KMP, поэтому beforeEvaluate в subprojects). - .gitea/workflows/ci.yml (новый): build + jvmTest + shadowJar на PR/push main. - .gitea/workflows/release.yml (обновлён): публикует библиотеки в caffeine Nexus + собирает 3 fatjar'а и крепит их к release как бинарные ассеты.
:proto — pw.binom.agentik.proto
Stateful KMP-протокол взаимодействия клиента с агентом. Замена AG-UI в проектах, где агенту нужно самому владеть историей диалога и контекстным окном (компакция, рефлексия, выбор инструментов) — клиент только стримит сообщения и рисует события.
Какую проблему решает
AG-UI требует, чтобы клиент слал полный messages[] на каждый ход, а агент
оставался stateless. Это удобно для UI-чатов, но ломается, когда:
- у агента есть долговременная память (md/vector), и контекст должен автоматически сжиматься / дополняться перед отправкой в LLM;
- у одного пользователя десятки активных диалогов и нельзя каждый раз пересылать 100K токенов;
- агент сам планирует вызовы инструментов и управляет KV-cache модели.
:proto переворачивает ответственность: агент владеет Conversation.messages(),
send(content) отправляет только новый message, а events(after): Flow<Event>
стримит live-события с Instant-таймстампом для отслеживания прогресса.
Контракт
interface Agent {
val id: String
suspend fun createConversation(temp: Boolean = false): Conversation
suspend fun getConversation(id: String): Conversation?
suspend fun getConversations(offset: Int = 0, limit: Int = PAGE_SIZE): List<Conversation>
fun getConversations(offset: Int = 0): Flow<Conversation> // cold-flow по страницам
fun events(after: Instant): Flow<AgentEvent> // live-уведомления о диалогах
}
interface Conversation : AutoCloseable {
val id: String
val title: String?
val updatedAt: Instant
val isSupportImageInput: Boolean
val isSupportImageOutput: Boolean
suspend fun send(content: List<Content>): Unit // write-only, не блокирует
fun events(after: Instant): Flow<Event> // live read (НЕ replay!)
suspend fun getMessages(offset: Int, limit: Int = PAGE_SIZE): List<Message>
fun getMessages(offset: Int = 0): Flow<Message> // cold-flow по страницам
suspend fun rename(title: String): Boolean
suspend fun interrupt(): Unit
fun close() // освобождает ресурсы
}
Иерархии:
Content—Text/Image(data: ByteArray, mime: String)Message—UserMessage/AssistantMessage(обаBody) +ToolCall(id, name, args)/ToolResult(id, result)/Systemдля метаданныхEvent—StartReasoning/StartResponse(type)/AppendText/AppendImage/End/Interrupted/ErrorAgentEvent—Created(id)/Deleted(id)/Renamed(id, title)
Live-стримы (events(after)) не реплеят прошедшие события — клиент должен
сам вызвать getMessages(after) для бэкфилла, либо подписаться на events(after=now)
и начать рисовать с настоящего момента.
Подключение
Артефакт — pw.binom.agentik:proto:VERSION.
// commonMain
implementation("pw.binom.agentik:proto:$version")
// JVM-only
implementation("pw.binom.agentik:proto-jvm:$version")
// Любой KMP-таргет
implementation("pw.binom.agentik:proto-macosArm64:$version")
version синхронизируется с gradle.properties (version=0.1.0) и
прокидывается через -Pversion=... в CI (binom.repo.* для Nexus).
Где смотреть версии
- текущая разрабатываемая:
gradle.properties→version=0.1.0 - история релизов:
https://git.binom.pw/subochev/agentik/releases - опубликованные артефакты: Nexus-репозиторий
caffeine(http://nexus.xx/repository/caffeine/pw/binom/agentik/proto/)
Сборка / тесты
./gradlew :proto:build # все KMP-таргеты + тесты
./gradlew :proto:jvmTest # только JVM-тесты
./gradlew :proto:publishToMavenLocal # для локального потребления
KMP-таргеты: jvm + macosX64 + macosArm64 + iosX64 + iosArm64 + iosSimulatorArm64 + linuxX64 + linuxArm64 + mingwX64.
Зависимостей минимум: kotlinx-coroutines-core:1.11.0 + kotlinx-datetime:0.8.0 (оба api).