docs: per-module READMEs (run vs library) + root navigation hub
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]
This commit is contained in:
SubochevAV
2026-09-16 20:44:16 +03:00
parent 5ad972767d
commit 8f616f359f
22 changed files with 1125 additions and 890 deletions
+79 -82
View File
@@ -1,106 +1,103 @@
# :agentik-tui — Compose-for-Mosaic TUI клиент к /agentik
# `:agentik-tui` — Compose-for-Mosaic TUI-клиент к `/agentik`
Compose-style TUI-клиент (KMP desktop, без iOS), рендерится в ANSI-терминал
через библиотеку [Mosaic](https://github.com/JakeWharton/mosaic) 0.18. Полная
клавиатурная навигация — никаких `:`-префиксов (как в vim).
## Что это
## Сборка
Compose-style TUI-клиент в терминале на базе
[Mosaic](https://github.com/JakeWharton/mosaic) (Jetpack Compose
runtime, рендерится в ANSI-коды). Без `:`-команд (без vim-style
prompt): клавиатурная навигация Tab/Enter/Esc/Ctrl-D/F1/стрелки +
жирный focus indicator.
- **Layout**: header (id/conv/focus) + history + input + footer.
- **Focus**: Tab/Shift-Tab цикл по фокусам (input → history → sidebar).
- **Input**: стандартное текстовое поле с курсором `|` посередине.
- **Stream**: подписка на SSE в фон-корутинах, `StateFlow` + `collectAsState()`
для UI-реактивности (см. Snake sample).
Решает: полноценный TUI-клиент для тех, кто предпочитает мышкой
кликать в терминале больше, чем печатать. В отличие от `:agentik-cli`,
показывает историю диалога и текущий стрим в одном окне.
## Как запустить
### Требования
- JVM 21+.
- Запущенный `:standalone` (по умолчанию `http://localhost:8080/agentik`).
- Реальный TTY (через `ssh -tt`, `tmux`, либо нативный terminal).
### Запуск из готового fatjar
```bash
./gradlew :agentik-tui:shadowJar
# Результат: agentik-tui/build/libs/agentik-tui-all.jar (~10 MB)
java --enable-native-access=ALL-UNNAMED \
-jar agentik-tui-0.1.0-all.jar \
--server http://192.168.76.166:8080/agentik
```
Также доступен через Nexus (`caffeine` репо) — `pw.binom.agentik:agentik-tui:VERSION`.
`--enable-native-access=ALL-UNNAMED` обязателен — Mosaic использует
native syscalls для терминала.
## Запуск
### Запуск через Gradle (dev)
```bash
# По умолчанию — http://localhost:8080/agentik
java --enable-native-access=ALL-UNNAMED \
-jar agentik-tui-all.jar
# К другому серверу
java --enable-native-access=ALL-UNNAMED \
-jar agentik-tui-all.jar --server http://192.168.76.166:8080/agentik
# Без восстановления последней беседы
java --enable-native-access=ALL-UNNAMED \
-jar agentik-tui-all.jar --no-history
# Конкретная беседа
java --enable-native-access=ALL-UNNAMED \
-jar agentik-tui-all.jar --id <conversation-uuid>
./gradlew :agentik-tui:run --args="--server http://localhost:8080/agentik"
```
Альтернативно: `AGENTIK_SERVER` env-переменная.
## Параметры CLI
> **`--enable-native-access=ALL-UNNAMED`** обязателен: Mosaic использует
> нативные API терминала (`stdin`/`stdout` raw mode), что требует
> `--enable-native-access`.
## Клавиши
| Клавиша | Действие |
|---|---|
| **Tab** / **Shift-Tab** | переключение фокуса: input → history → sidebar → … |
| **Enter** | отправить набранное сообщение |
| **Backspace** / **Delete** | удалить символ |
| **←/→** / **Home/End** | курсор в input |
| **↑/↓** | scrollback (в фокусе на history) / input history (в фокусе на input) |
| **Esc** | очистить input |
| **F1** | показать/скрыть help overlay |
| **Ctrl-D** / **Ctrl-C** | прервать активный ход (повторное нажатие — выход) |
`:`-префикс команд **отключён намеренно** — для отправки команд используются
клавиши. Если нужно сделать что-то нестандартное — переключитесь на `:agentik-cli`
(REPL с slash-командами).
## Переменные окружения
| Переменная | Дефолт | Назначение |
| Флаг | ENV | Что делает |
|---|---|---|
| `AGENTIK_SERVER` | `http://localhost:8080/agentik` | URL HTTP-фасада `:server` |
| `--server URL` | `AGENTIK_SERVER` | URL `/agentik` (default `http://localhost:8080/agentik`) |
| `--id ID` | `USER`/`USERNAME` | Имя агента (default — текущий пользователь) |
| `--no-history` | — | Не восстанавливать последнюю диалог после запуска |
| `--help` | — | Показывает help и выходит |
История сессий: `~/.agentik/tui-state.json`.
## Keybindings
## Layout
| Клавиша | Когда | Что делает |
|---|---|---|
| `Tab` / `Shift-Tab` | глобально | Цикл фокусов: input → history → sidebar → ... |
| `F1` | глобально | Toggle help overlay |
| `Esc` | в input | Очистить input |
| `Enter` | в input | Submit message |
| `Backspace` / `Del` | в input | Удалить символ |
| `←` `→` `Home` `End` | в input | Курсор |
| `↑` `↓` | в history | Scrollback |
| `Ctrl-D` / `Ctrl-C` | — | Exit (TODO — пока работает только вне стрима) |
```
┌────────────────────────────────────────────────────────────────┐
│ agentik · agent-id · <conv-uuid> · focus=input │ ← header
├────────────────────────────────────────────────────────────────┤
│ │
│ [User 14:32] │
│ привет │
│ │
│ [Bot 14:32] │
│ привет! чем помочь? │ ← history (scroll)
│ ▍ │
│ │
├────────────────────────────────────────────────────────────────┤
│ > | | │ ← input (cursor)
├────────────────────────────────────────────────────────────────┤
│ Tab focus ↑↓ scroll Enter send Esc clear F1 help ⌃D exit │ ← footer
└────────────────────────────────────────────────────────────────┘
```
## Переменные среды (сервера)
## Что пока работает и что нет
См. [`../standalone/README.md`](../standalone/README.md). TUI
получает URL сервера через `--server`, остальное настройка
агента, а не клиента.
✅ header + history + input + footer
✅ focus cycling (Tab / Shift-Tab)
✅ input editing (chars, BS, Del, ←/→, Home/End, Enter)
✅ история input'а через ↑/↓ (в фокусе на input)
✅ scrollback history (в фокусе на history)
✅ F1 help overlay
✅ Ctrl-D / Ctrl-C interrupt
## Известное ограничение
⌛ mouse support (термиос SGR-mouse parsing) — для v3+.
⌛ split-pane (history left / input right) — пока input внизу, full-width.
⌛ `:agentik-cli`-slash-команды внутри TUI (history backfill / list / switch).
1. **SSE в не-TTY ssh закрывается на default Ktor timeout** — то
же, что для `:agentik-cli`.
2. **Mouse events не подключены** в v2 (Mosaic 0.18 не имеет
built-in mouse-runtime). Планируется в v3 через termios
SGR-mouse.
3. **Нативные target'ы (macOS / Linux x64+ARM64 / Windows x64)**
собраны, но без `:client` (он JVM-only). Для нативной работы
нужен альтернативный HTTP-клиент.
## Тесты
```bash
```
./gradlew :agentik-tui:jvmTest
```
Тесты composable'ов и event-рендеринга. Включает smoke-test для
key-event → AppState mutation → ре-рендер.
## Версии
`gradle/libs.versions.toml` → `[versions] agentik-agentik-tui`.
## Архитектурная заметка
UI-стейт держится в `StateFlow`, а **не** в Compose `mutableStateOf`.
Причина: Mosaic 0.18 не триггерит recomposition от `mutableStateOf`
-writes внутри `onPreviewKeyEvent`-handler'ов (см. Snake sample в
репо Mosaic — они тоже используют `StateFlow` + `collectAsState()`).