ee0b9d8341
ci / JVM build + tests (push) Failing after 1m25s
Пользователь признал TUI-подход неудачным (Mosaic 0.18 требует alt-screen
костылей, нативный ввод/вывод ограничен, тестирование через pty).
Папка agentik-tui/ оставлена на диске — комментарий в settings.gradle.kts
фиксирует дату и причину, на случай если вернёмся.
Изменения:
- settings.gradle.kts: include(':agentik-tui') → закомментировано
- build.gradle.kts: убран из moduleDescriptions
- .gitea/workflows/ci.yml: убран shadowJar шаг и из upload paths
- .gitea/workflows/release.yml: убран из комментария
- README.md, proto/README.md, server/README.md, client/README.md:
ссылки на :agentik-tui помечены как устаревшие
- agentik-cli/build.gradle.kts: убрана ссылка в комментарии
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-cli` — JVM/native CLI-клиент поверх `:client`.
|
|
- Любой внешний 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.
|