- Remove legacy pw.binom.agentik.messageStore.events.EventStore (EventRecord,
EventType) and all three impls (in-memory, sqlite, ksqlite) + tests + .sq
- Drop :storage-bundle module entirely; ChatAgent / ChatConversation /
ConversationLoop / DebugRoutes now take stores individually
(conversationStore, messageStore, workingMemoryStore, reflectionStore,
eventStore) instead of StorageBundle
- Delete server endpoints /events/replay and /conversations/{id}/events/replay;
Route.agentikAgent no longer takes eventStore param
- Add :client/HttpEventStore implementing :event-store/EventStore over HTTP:
events() -> GET /events/all, agentEvents() -> GET /events,
conversationEvents(convId) -> GET /conversations/{id}/events;
exposed via AgentClient.eventStore
- :event-store: add macosX64/macosArm64/linuxArm64 targets to match :client KMP
- :working-memory-api: drop api dep on :message-store-api (no longer needed)
- :storage-{inmemory,sqlite,ksqlite}: drop deps on :storage-bundle
- :agentik-cli переписан с REPL на one-shot subcommands:
conv-ls / conv-new / conv-show / conv-delete / conv-rename /
msgs / send / interrupt / info. Аргумент-парсер — kotlinx.cli 0.3.6
(clikt 5.x отвергнут из-за upstream-бага duplicate symbol
selfAndAncestors между clikt и clikt-mordant, issue #598).
- :client: events() переведён с httpClient.get() на
prepareGet()+execute{} — get() дожидается полного тела, а SSE
не закрывается никогда, поэтому подписка висела вечно. (Это
же объясняет, почему TUI agent.events() фактически был
нерабочим на реальном сервере.)
- :client KMP-конверсия (jvm + 5 desktop-native) уже была в
коммите 9d826a4, здесь она просто подтверждена в статусе
green по всем таргетам.
- REPL-инфраструктура (CliPlatform, EventRenderer, Main,
SessionRepository, SlashCommand + 3 теста) удалена.
- agentik-cli/README переписан под subcommand-формат,
root README обновлён (убран дубликат строки, agentik-tui
убран из 'Запускаемые модули').
Smoke (на 192.168.76.166): info / conv-ls / conv-new /
conv-rename / conv-show / conv-delete / msgs / send
(стримит response-events до event End) / interrupt
(выводит event Interrupted).
Дефолтный CIOEngineConfig.requestTimeout = 15 с убивал SSE-стрим при
простое, потому что движок CIO не считает запрос SSE-шным (мы читаем
bodyAsChannel() руками, без SSEClientContent). На TUI это проявлялось как
'стрим отвалился через 15 с' — события молча переставали приходить.
Два уровня фикса:
1. Per-request: HttpRequestBuilder.noSseReadTimeout() ставит capability
HttpTimeoutCapability со всеми таймаутами = INFINITE_TIMEOUT_MS.
В ConversationClient.events() и AgentClient.events() вызывается перед
каждым SSE-стримом. Плагин HttpTimeout (если установлен) читает эту
capability через ?: и не перезаписывает её.
2. Default client: defaultAgentikHttpClient() ставит
engine { requestTimeout = 0 } — defense-in-depth на случай, если
кто-то соберёт свой HttpClient без capability.
Тесты:
- SseTimeoutTest запускает встроенный Ktor CIO-сервер, держит stream 17 с.
- 'with noSseReadTimeout' — stream живёт до 'done' (тест проходит ~17 с).
- 'without noSseReadTimeout' — клиент падает на ~15 с с
HttpRequestTimeoutException (контр-тест, доказывает что баг был).
- build.gradle.kts (root): настроен maven-publish для всех сабпроектов;
репо 'caffeine' (Nexus) с setAllowInsecureProtocol=true, POM-метаданные
(Apache-2.0, subochev as developer, scm). Version берётся из -Pversion=<tag>
с fallback 0.1.0.
- gradle.properties: дефолтная version=0.1.0 для локальных билдов.
- .gitea/workflows/release.yml: триггер на release.published; две job'ы —
publish-libraries (subochev/devops/publish action с BINOM_REPO_* env-vars)
и build-standalone (собирает :standalone shadowJar, прикрепляет
standalone-<version>-all.jar и sources.jar к release assets через
softprops/action-gh-release + GITEA_TOKEN).
- В пяти KMP-модулях (skills, storage-core, agent-toolsets, server, client)
добавлен api(libs.kotlinx.serialization.core) — раньше commonMain
компилировался только на JVM, и эта зависимость была пропущена; теперь
commonMain корректно публикуется как Gradle Module Metadata.
Локальная проверка:
./gradlew publishToMavenLocal — все 11 модулей × 9-10 таргетов
./gradlew jvmTest — все тесты зелёные
./gradlew :standalone:shadowJar — 240MB fatjar, Main-Class загружается
Major additions:
* :proto (KMP submodule) — in-house stateful protocol replacing AG-UI.
Agent owns conversation transcript; Conversation.events(after) is a live,
replay-free stream; backfill via Conversation.getMessages(after, offset, limit).
Each Event carries an Instant date for client-side resume tracking.
Sealed hierarchies (Content/Message/Event/AgentEvent) annotated @Serializable
with snake_case @SerialName JSON discriminators so the wire format is
decoupled from Kotlin class names.
* :server (JVM, Ktor 3.1.3) — REST+SSE facade for Agent.
Public entry: Route.agentikAgent(agent, path = "/agentik").
Endpoints: create/list/get/patch/delete conversations, POST messages (202),
POST interrupt, GET messages, GET conversation events (SSE),
GET agent events (SSE), GET /health. Custom Instant serializer for
kotlin.time.Instant registered contextually on agentikJson (ISO-8601,
ignoreUnknownKeys=true, explicitNulls=false).
* :client (JVM, Ktor HTTP Client + CIO) — mirror of :server returning
a pw.binom.agentik.proto.Agent backed by HTTP calls. Custom SSE parser
since ktor-client-sse is not on the 3.1.3 client classpath.
* standalone — EchoProtoAgent (in-memory Agent for :proto), EchoAgent
(existing AG-UI echo), both mounted on the same Netty embedded server
on port 8080 (/agui and /agentik); A2A stays on its own CIO engine on
8081. EchoProtoAgent smoke-tested end-to-end against :server: all 11
endpoints, including live SSE delivery of StartResponse/AppendText/End
event triplets and Agent-level Created/Deleted events.
Design notes pinned in:
* agentik/IRC-QUESTIONS.md — closed 13-item checklist for the upcoming
:irc-server transport (channel = conversation, CTCP for structural
events, draft/chathistory for backfill, ImageStore side-channel, etc).
* docs/ARCHITECTURE.md — overall layout snapshot.