# :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` стримит live-события с `Instant`-таймстампом для отслеживания прогресса. ## Контракт ```kotlin 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 fun getConversations(offset: Int = 0): Flow // cold-flow по страницам fun events(after: Instant): Flow // live-уведомления о диалогах } interface Conversation : AutoCloseable { val id: String val title: String? val updatedAt: Instant val isSupportImageInput: Boolean val isSupportImageOutput: Boolean suspend fun send(content: List): Unit // write-only, не блокирует fun events(after: Instant): Flow // live read (НЕ replay!) suspend fun getMessages(offset: Int, limit: Int = PAGE_SIZE): List fun getMessages(offset: Int = 0): Flow // 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`. ```kotlin // 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/`) ## Сборка / тесты ```bash ./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`).