docs: per-module READMEs (run vs library) + root navigation hub
ci / JVM build + tests (pull_request) Failing after 54s
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:
+79
-82
@@ -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()`).
|
||||
|
||||
Reference in New Issue
Block a user