8f616f359f
ci / JVM build + tests (pull_request) Failing after 54s
Every subproject now has README.md:
- 3 runnable modules (:standalone, :agentik-cli, :agentik-tui):
quickstart, env table, parameters, known limits
- 11 library modules: what it is, which problem solves, how to
wire it in, where versions live
Root README.md is the navigation hub (Quickstart, Modules table,
publish + CI/CD notes).
Also: ci.yml prunes the :memory-vector -x excludes now that
text-embedding-kmp artifacts are published to caffeine.
518 tests green.
Verified publish pipeline: :proto:publish to caffeine produces
pom.module + per-target klibs + sources for all 9 KMP targets.
🤖 Generated with [opencode]
102 lines
3.4 KiB
Markdown
102 lines
3.4 KiB
Markdown
# `:client` — Ktor-клиент к `:server`/`:proto` (KMP, jvm + native)
|
|
|
|
## Что это
|
|
|
|
Ktor client (`io.ktor.client.HttpClient` + `ContentNegotiation(json) +
|
|
Sse`), превращающий HTTP/SSE-фасад `:server` в `Agent`/`Conversation`
|
|
интерфейсы `:proto`:
|
|
|
|
- `AgentikAgent(id, baseUrl)` — entry-point фабрики.
|
|
- `AgentClient` — список и lifecycle диалогов.
|
|
- `ConversationClient` — `send()`, `events()`, `interrupt()`,
|
|
`getMessages()`, `rename()`, `close()`.
|
|
- Внутренний парсер SSE → `Flow<Event>`.
|
|
|
|
Решает: пишем нативный Kotlin-клиент, без curl/JS/Python boilerplate,
|
|
с теми же типами, что и сервер. Один и тот же клиент работает на
|
|
JVM, iOS, macOS, Linux, Windows.
|
|
|
|
## Где используется
|
|
|
|
- `:agentik-cli` — REPL.
|
|
- `:agentik-tui` — Compose-for-Mosaic клиент.
|
|
- Любой внешний KMP-проект, который хочет встроить агента в свой UI.
|
|
|
|
## Как подключить
|
|
|
|
```kotlin
|
|
// build.gradle.kts
|
|
kotlin {
|
|
sourceSets.commonMain.dependencies {
|
|
api("pw.binom.agentik:client:0.1.0")
|
|
}
|
|
}
|
|
|
|
// ваш код:
|
|
val agent = AgentikAgent(id = "agentik", baseUrl = "http://192.168.76.166:8080/agentik")
|
|
val conv = agent.createConversation(title = "test")
|
|
conv.send(listOf(Content.Text("hello"))).collect { event ->
|
|
when (event) {
|
|
is Event.AppendText -> print(event.body)
|
|
is Event.End -> println("\n--- end ---")
|
|
is Event.Error -> error("agent error: ${event.message}")
|
|
else -> Unit
|
|
}
|
|
}
|
|
```
|
|
|
|
## Версии
|
|
|
|
`gradle/libs.versions.toml` → `[versions] agentik-client`.
|
|
|
|
Поддерживает все KMP-таргеты, что и `:proto`.
|
|
|
|
## Примеры API
|
|
|
|
```kotlin
|
|
// список диалогов
|
|
agent.getConversations().collect { println(it.id to it.title) }
|
|
|
|
// live-подписка на события отдельного диалога
|
|
val sub = conversation.events(after = Instant.parse("2026-09-01T00:00:00Z")).collect { }
|
|
|
|
// прерывание текущего хода
|
|
conversation.interrupt()
|
|
|
|
// история
|
|
conversation.getMessages(offset = 0).collect { msg ->
|
|
when (msg) {
|
|
is Message.UserMessage -> println("user: ${msg.content}")
|
|
is Message.AssistantMessage -> println("assistant: ${msg.content}")
|
|
else -> Unit
|
|
}
|
|
}
|
|
```
|
|
|
|
## Тесты
|
|
|
|
```
|
|
./gradlew :client:jvmTest
|
|
```
|
|
|
|
Покрывают: JSON-парсинг Event'ов, SSE-стрим, recovery после разрыва,
|
|
401/404.
|
|
|
|
## Чего здесь НЕТ
|
|
|
|
- Никакого LLM-кода. Это просто клиент.
|
|
- Никакого persistent state. История хранится у сервера, клиент её
|
|
запрашивает через `getMessages` или подписывается через `events`.
|
|
|
|
## Текущий статус
|
|
|
|
Используется продакшеном. Бэкендом служит `:server` поверх `:standalone`,
|
|
но клиент совместим с любым сервером, который держит wire-контракт
|
|
`:server`.
|
|
|
|
## Известное ограничение
|
|
|
|
SSE event-stream в не-TTY ssh-сессии (без `-tt`) закрывается на
|
|
default-таймауте Ktor. Используйте либо ssh -tt, либо нативный
|
|
terminal (TTY). Это upstream-особенность Ktor SSE.
|