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: убрана ссылка в комментарии
89 lines
3.8 KiB
Markdown
89 lines
3.8 KiB
Markdown
# `:server` — HTTP/SSE фасад для `:proto` (KMP, JVM-only)
|
||
|
||
## Что это
|
||
|
||
Ktor-маршрут, экспонирующий `Agent` из `:proto` в виде JSON-API:
|
||
`POST /agentik/conversations`, `POST /agentik/conversations/:id/send`,
|
||
`GET /agentik/conversations/:id/events` (SSE), `GET /health`,
|
||
`GET /agentik/conversations`.
|
||
|
||
- **stateful** — сервер не принимает полную историю, только новые
|
||
сообщения. История хранится там, где развёрнут `Agent`.
|
||
- **декларативно** — `interface Agent` → HTTP; никакой магии, никаких
|
||
обёрток. Контракт и сериализация — тоже декларативные (kotlinx-json
|
||
с snake_case-дискриминаторами).
|
||
|
||
Решает: позволяет собрать любой собственный front-end (CLI/TUI/Web/
|
||
IRC/MCP) общаясь с одним сервером по стабильному wire-контракту.
|
||
|
||
## Где используется
|
||
|
||
- `:standalone` подключает `Route.agentikAgent(agent)` в свой
|
||
embedded Netty engine.
|
||
- Любые клиенты (наши `:client`, `:agentik-cli`, или
|
||
внешние web-фронтенды) идут через этот контракт.
|
||
|
||
## Как подключить
|
||
|
||
```kotlin
|
||
// build.gradle.kts (KMP JVM target)
|
||
plugins { id("pw.binom.agentik.server-conventions") version "0.1.0" }
|
||
dependencies {
|
||
api("pw.binom.agentik:server:0.1.0")
|
||
api("pw.binom.agentik:proto:0.1.0")
|
||
}
|
||
|
||
// ваш код:
|
||
fun Application.module(agent: Agent) {
|
||
install(ContentNegotiation) { json(agentikJson) }
|
||
install(SSE)
|
||
routing {
|
||
route("/agentik") { agentikAgent(agent) }
|
||
}
|
||
}
|
||
```
|
||
|
||
## Версии
|
||
|
||
`gradle/libs.versions.toml` → `[versions] agentik-server`.
|
||
|
||
## Эндпоинты (path по умолчанию `/agentik`, через `agentikAgent(agent, "/my")`)
|
||
|
||
| Метод | Путь | Что делает |
|
||
|---|---|---|
|
||
| `POST` | `/conversations` | Создать диалог (body: `{title?}`) |
|
||
| `GET` | `/conversations` | Список диалогов (по `?offset=&limit=`) |
|
||
| `GET` | `/conversations/:id` | Снимок диалога + count |
|
||
| `GET` | `/conversations/:id/messages` | История сообщений (по `?after=`) |
|
||
| `POST` | `/conversations/:id/rename` | Переименовать (body: `{title}`) |
|
||
| `DELETE` | `/conversations/:id` | Удалить |
|
||
| `POST` | `/conversations/:id/send` | Send-флоу (body: `{content:[…]}` → SSE) |
|
||
| `GET` | `/conversations/:id/events` | Live подписка (SSE) |
|
||
| `POST` | `/conversations/:id/interrupt` | Прервать текущий `send()` |
|
||
|
||
`Content-Type: text/event-stream` всегда для SSE, ноль-лишних
|
||
заголовков. Сообщения: `event: <name>` (`message`, `start_reasoning`,
|
||
`start_response`, `append_text`, `append_image`, `end`, `interrupted`,
|
||
`error`) + `data: <JSON>`.
|
||
|
||
## Тесты
|
||
|
||
```
|
||
./gradlew :server:jvmTest
|
||
```
|
||
|
||
Покрывают: маппинг JSON ↔ Event, SSE framing, error-handling,
|
||
404 / 400 ответы, корректную обработку `Instant` в `kotlinx-datetime`.
|
||
|
||
## Чего здесь НЕТ
|
||
|
||
- Никакого LLM-кода, tool-вызовов, прерываний. Только mapping Agent ↔ HTTP.
|
||
- Никакой БД, никакого storage. Это задача `Agent`-имплементации.
|
||
- Никакого CORS-конфига по умолчанию — добавляйте на свой engine.
|
||
|
||
## Текущий статус
|
||
|
||
Используется продакшеном. Wire-контракт стабильный; новые Event'ы
|
||
добавляются только с snake_case-дискриминаторами и строго обратно
|
||
совместимо.
|