Files
agentik/proto
subochev 0fdc12695e
ci / JVM build + tests (push) Failing after 1m57s
docs: per-module README + root navigation hub + CI/release workflows
- 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 как бинарные ассеты.
2026-09-16 16:24:03 +03:00
..

: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 / Error
  • AgentEvent — 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).