850ee99cb6
ci / JVM build + tests (push) Failing after 2m3s
- Добавил нативные таргеты с реальной реализацией (не stub-ы):
- linuxX64 kexe ~5 МБ — собран, запускается, проходит
smoke против 192.168.76.166 (--help, info, conv-ls,
conv-new, send со стримом response-events, AGENTIK_SERVER
env-переменная).
- mingwX64 .exe ~6 МБ — собирается через кросс-компиляцию с Linux.
- macosX64 / macosArm64 — на Linux-хосте не линкуются (нужен
macOS-раннер, Apple Mach-O), но target-объявления + entryPoint
валидны.
- entryPoint на K/N — FQN без 'Kt': pw.binom.agentik.cli.main
(на JVM по-прежнему AgentikCliKt через mainClass.set).
- platformEnv: expect/actual split. Native actual — getenv()
из platform.posix через kotlinx.cinterop, помеченный
@OptIn(ExperimentalForeignApi::class).
- linuxArm64 у :agentik-cli отсутствует — kotlinx.cli 0.3.6 не
публикует klib для linuxArm64. У :client linuxArm64 сохранён
(асимметрия допустима: :client нужен только :agentik-cli,
который на linuxArm64 не работает).
- README обновлён: target matrix, env-vars, native entry-point,
платформенные детали.
161 lines
6.3 KiB
Markdown
161 lines
6.3 KiB
Markdown
# `:agentik-cli` — one-shot CLI клиент к `/agentik`
|
||
|
||
## Что это
|
||
|
||
**One-shot subcommand CLI** (Kotlin Multiplatform) к серверу
|
||
`:standalone` через `:client` по HTTP+SSE. Один вызов — одна команда:
|
||
стрим ответа `send` идёт в stdout построчно, никакого embedded-REPL.
|
||
|
||
Решает: быстрый способ дёрнуть агента из shell-скрипта или руками,
|
||
не поднимая отдельную TUI-сессию.
|
||
|
||
## Платформы
|
||
|
||
| Платформа | Артефакт | Размер | Статус |
|
||
|---|---|---|---|
|
||
| `jvm` (JRE 21) | `*-all.jar` | ~7 МБ | ✓ собирается и работает |
|
||
| `linuxX64` | `.kexe` | ~5 МБ | ✓ собирается и работает на этом хосте |
|
||
| `macosX64` | `.kexe` | — | собирается на macOS-раннере |
|
||
| `macosArm64` | `.kexe` | — | собирается на macOS-arm64-раннере |
|
||
| `mingwX64` | `.exe` | ~6 МБ | ✓ собирается (cross-compile с Linux) |
|
||
| `linuxArm64` | — | — | **нет** — kotlinx-cli 0.3.6 не публикует klib для linuxArm64 |
|
||
| `iOS` | — | — | нет смысла на iOS |
|
||
|
||
## Подкоманды
|
||
|
||
```
|
||
agentik-cli <subcommand> [options]
|
||
|
||
Subcommands:
|
||
conv-ls Список диалогов агента
|
||
conv-new Создать диалог; печатает id
|
||
conv-show Метаданные диалога
|
||
conv-delete Удалить диалог
|
||
conv-rename Переименовать диалог
|
||
msgs Показать сообщения диалога
|
||
send Отправить user-ход и стримить ответ
|
||
interrupt Прервать текущий ход диалога
|
||
info Показать server URL и agent id
|
||
```
|
||
|
||
`--server URL` и `--id ID` (env: `AGENTIK_SERVER`, `AGENTIK_AGENT_ID`)
|
||
задаются **после** имени subcommand'а — kotlinx.cli не шарит опции
|
||
родителя в subcommand. Пример:
|
||
|
||
```bash
|
||
agentik-cli conv-ls --server http://192.168.76.166:8080/agentik
|
||
agentik-cli conv-new --server http://localhost:8080/agentik
|
||
agentik-cli send --server http://localhost:8080/agentik conv-abc "привет"
|
||
```
|
||
|
||
## Как запустить
|
||
|
||
### JVM (fatjar)
|
||
|
||
```bash
|
||
./gradlew :agentik-cli:shadowJar
|
||
java --enable-native-access=ALL-UNNAMED \
|
||
-jar agentik-cli/build/libs/agentik-cli-0.1.0-SNAPSHOT-all.jar --help
|
||
```
|
||
|
||
### Native linuxX64
|
||
|
||
```bash
|
||
./gradlew :agentik-cli:linkReleaseExecutableLinuxX64
|
||
./agentik-cli/build/bin/linuxX64/releaseExecutable/agentik-cli.kexe --help
|
||
```
|
||
|
||
### Native macOS / Windows
|
||
|
||
На Linux-хосте `macosX64`/`macosArm64` линкуются пустыми (нужен
|
||
macOS-раннер, Apple Mach-O формат). `mingwX64` собирается через
|
||
кросс-компиляцию.
|
||
|
||
CI-ноут: запускать `./gradlew :agentik-cli:linkReleaseExecutableMacosX64
|
||
:agentik-cli:linkReleaseExecutableMacosArm64` на `macos-latest`
|
||
раннере Gitea Actions.
|
||
|
||
## Примеры
|
||
|
||
```bash
|
||
# Список диалогов (таблица)
|
||
agentik-cli conv-ls --server http://localhost:8080/agentik
|
||
|
||
# Создать диалог
|
||
ID=$(agentik-cli conv-new --server http://localhost:8080/agentik)
|
||
echo "new conv: $ID"
|
||
|
||
# Переименовать
|
||
agentik-cli conv-rename --server http://localhost:8080/agentik "$ID" "мой чат"
|
||
|
||
# Отправить ход и стримить ответ
|
||
agentik-cli send --server http://localhost:8080/agentik "$ID" "2+2"
|
||
|
||
# Показать последние N сообщений
|
||
agentik-cli msgs --server http://localhost:8080/agentik "$ID" --limit 10
|
||
|
||
# Прервать активный ход
|
||
agentik-cli interrupt --server http://localhost:8080/agentik "$ID"
|
||
|
||
# Удалить
|
||
agentik-cli conv-delete --server http://localhost:8080/agentik "$ID"
|
||
|
||
# Через env-переменную
|
||
AGENTIK_SERVER=http://localhost:8080/agentik agentik-cli info
|
||
```
|
||
|
||
## Формат вывода `send`
|
||
|
||
Каждое SSE-событие печатается отдельной строкой `event <Type> ...` —
|
||
пригодно для парсинга через `awk`/`jq`-обёртки:
|
||
|
||
```
|
||
event StartReasoning
|
||
event StartResponse TEXT
|
||
event AppendText \n\n
|
||
event AppendText Привет!
|
||
event End
|
||
```
|
||
|
||
Терминальные события (`End`, `Interrupted`, `Error`) тоже
|
||
печатаются; CLI выходит сразу после `End`.
|
||
|
||
## Почему kotlinx.cli (а не clikt)
|
||
|
||
- **kotlinx.cli 0.3.6** (JetBrains, KMP) — единственный зрелый
|
||
arg-parser, который стабильно линкуется под `linux_x64` +
|
||
`macos_x64`/`macos_arm64` + `mingw_x64`. Минус: нет `linux_arm64`.
|
||
- **clikt-multiplatform 5.x** (ajalt) — имеет linuxArm64, но
|
||
ломается на native linker: `duplicate symbol selfAndAncestors`
|
||
между `clikt` и `clikt-mordant` commonMain (issue
|
||
[ajalt/clikt#598](https://github.com/ajalt/clikt/issues/598)).
|
||
Workaround `kotlin.native.cacheKind.linuxX64=none` замедляет
|
||
сборку на порядки и не решает проблему до конца. Поэтому clikt
|
||
отвергнут.
|
||
|
||
## Платформенные детали
|
||
|
||
- **entryPoint на K/N** — это FQN функции **без** суффикса `Kt`
|
||
(т.е. `pw.binom.agentik.cli.main`, а не `MainKt.main`). JVM
|
||
convention `MainKt.main` тут не работает — K/N линкер ищет
|
||
функцию по `package.main`.
|
||
- **`platformEnv(key)`** для чтения env-переменных:
|
||
- JVM: `System.getenv(key)` через `jvmMain` actual.
|
||
- Native: `getenv(key)` из `platform.posix` через
|
||
`kotlinx.cinterop.toKString()` (`nativeMain` actual,
|
||
требует `@OptIn(ExperimentalForeignApi::class)`).
|
||
- **Stdout / exit code** — работают на K/N через корутины.
|
||
|
||
## Тесты
|
||
|
||
Тесты для подкоманд пока не написаны (TODO). Базовый smoke
|
||
покрывается руками против живого сервера.
|
||
|
||
```bash
|
||
./gradlew :agentik-cli:jvmTest # 0/0 — пока пусто
|
||
```
|
||
|
||
## Версии
|
||
|
||
`gradle/libs.versions.toml` → `[versions] agentik-agentik-cli`.
|