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:
+118
-128
@@ -1,154 +1,144 @@
|
||||
# :standalone — agentik single-jar server
|
||||
# `:standalone` — single-jar HTTP-сервер со всеми транспортами
|
||||
|
||||
Self-contained HTTP-сервер на Ktor: AG-UI / A2A / :proto транспорты на одном порту,
|
||||
встроенный SQLite для истории диалогов, долговременная память (Hermes-style
|
||||
§-файлы или vector+JVector), загрузка MCP-инструментов, навыков (SKILL.md) и
|
||||
персоны (SOUL.md).
|
||||
## Что это
|
||||
|
||||
## Сборка
|
||||
Главный исполняемый модуль проекта — single-jar HTTP-сервер с:
|
||||
|
||||
- **AG-UI** transport на `POST /agui` (SSE) + `GET /health`.
|
||||
- **A2A** transport на `POST /` (JSON-RPC) + `GET /.well-known/agent-card.json`.
|
||||
- **`:proto`** transport на `POST /agentik/*` (HTTP+JSON+SSE) — наш stateful.
|
||||
- **Embedded LLM backend**: `GOOGLE` (LiteRT) или `OPENAI`-совместимый
|
||||
(vLLM, LiteLLM, OpenAI API).
|
||||
- **SQLite persistence** через `:storage-sqlite`.
|
||||
- **Memory backend**: `md` (файловый) или `vector` (SQLite+JVector+
|
||||
HTTP/SIGLIP-embeddings).
|
||||
- **Skills** из `~/.agentik/skills/*.md`.
|
||||
- **SOUL** из `~/.agentik/SOUL.md`.
|
||||
- **Background подпроцессы**: рефлексия, skill-mining,
|
||||
memory-reviewer.
|
||||
|
||||
Решает: даёт пользователю один JAR (10–250 МБ), который запускается
|
||||
через `java -jar agentik-0.1.0-all.jar`, и поднимает сразу все
|
||||
транспорты, которые другие системы могут хавать.
|
||||
|
||||
## Как запустить
|
||||
|
||||
### Требования
|
||||
|
||||
- JVM 21+.
|
||||
- (Опционально) CUDA-устройство для `:backend=google` (LiteRT).
|
||||
- (Опционально) LM через OpenAI-совместимый endpoint (vLLM / Ollama
|
||||
/ OpenAI) для `:backend=openai`.
|
||||
|
||||
### Запуск из готового fatjar
|
||||
|
||||
```bash
|
||||
# Полная сборка всего проекта + fatjar
|
||||
./gradlew assemble
|
||||
|
||||
# Только fatjar :standalone (≈ 250 MB)
|
||||
./gradlew :standalone:shadowJar
|
||||
|
||||
# Результат:
|
||||
# standalone/build/libs/standalone-all.jar
|
||||
java --enable-native-access=ALL-UNNAMED \
|
||||
-jar agentik-0.1.0-all.jar
|
||||
```
|
||||
|
||||
Также публикуется в Nexus (`caffeine` репо) при создании релиза:
|
||||
`pw.binom.agentik:standalone:VERSION` с classifier `all` (см.
|
||||
`https://git.binom.pw/subochev/agentik/releases`).
|
||||
С дефолтами — встроенный SQLite, OpenAI-compatible backend на
|
||||
`http://localhost:8001/v1`, порт 8080.
|
||||
|
||||
## Запуск
|
||||
### Запуск через Gradle (dev)
|
||||
|
||||
```bash
|
||||
java -jar standalone/build/libs/standalone-all.jar
|
||||
./gradlew :standalone:run
|
||||
```
|
||||
|
||||
По умолчанию слушает на `http://localhost:8080`. Healthcheck: `GET /health`.
|
||||
|
||||
Транспорты на одном порту:
|
||||
- `GET /health` — liveness
|
||||
- `POST /agentik/conversations` — создать беседу
|
||||
- `GET /agentik/conversations/{id}/events` — SSE-стрим ответов
|
||||
- `POST /a2a/` — A2A JSON-RPC (`message/send`, `tasks/get`, `tasks/cancel`)
|
||||
- `GET /a2a/.well-known/agent-card.json` — AgentCard
|
||||
- `POST /agui` — AG-UI (compatibility transport, legacy)
|
||||
|
||||
### Подкоманды
|
||||
### `pull-model` subcommand (для LiteRT)
|
||||
|
||||
```bash
|
||||
# Скачать модель Google LiteRT-LM в AGENTIK_GOOGLE_MODEL_PATH.
|
||||
# Требует AGENTIK_LLM_BACKEND=google. Если файл уже есть — no-op.
|
||||
java -jar standalone-all.jar pull-model
|
||||
|
||||
# Сервер (по умолчанию)
|
||||
java -jar standalone-all.jar
|
||||
# Сначала скачать модель под LiteRT-Gemma-4-E2B
|
||||
AGENTIK_LLM_BACKEND=google \
|
||||
AGENTIK_GOOGLE_MODEL_PATH=/root/gemma-4-E2B-it.litertlm \
|
||||
java --enable-native-access=ALL-UNNAMED \
|
||||
-jar agentik-0.1.0-all.jar pull-model
|
||||
```
|
||||
|
||||
## Переменные окружения
|
||||
Скачивает `https://static.binom.pw/models/gemma-4-E2B-it.litertlm`
|
||||
(2.5 ГБ, с Range-resume). Поддерживает override через
|
||||
`AGENTIK_GOOGLE_MODEL_URL` и verify через
|
||||
`AGENTIK_GOOGLE_MODEL_SHA256_URL`.
|
||||
|
||||
Все переменные читаются `AgentikConfig.fromEnv()`. Пусто или отсутствие → дефолт.
|
||||
## Переменные среды
|
||||
|
||||
| Переменная | Дефолт | Назначение |
|
||||
Полный список — общий для всего `:standalone`-процесса:
|
||||
|
||||
| Env | Default | Что делает |
|
||||
|---|---|---|
|
||||
| `AGENTIK_PORT` | `8080` | Порт HTTP-сервера |
|
||||
| `AGENTIK_DB_PATH` | `./agentik.db` | Путь к SQLite (история бесед + метаданные памяти) |
|
||||
| `AGENTIK_SKILLS_DIR` | _выкл._ | Каталог со скилами (`SKILL.md` / `*.yaml`) |
|
||||
| `AGENTIK_MEMORY_DIR` | `~/.agentik/memory` (md) или `AGENTIK_DB_PATH` (vector) | Каталог памяти (md); `"off"` отключает |
|
||||
| `AGENTIK_MEMORY_BACKEND` | `md` | `md` (Hermes-style §-файлы) / `vector` (SQLite + JVector + LLM-эмбеддинги) / `off` |
|
||||
| `AGENTIK_EMBEDDING_MODEL` | `text-embedding-3-small` | Модель эмбеддингов для vector-бэкенда (только HTTP) |
|
||||
| `AGENTIK_EMBEDDING_DIMENSION` | `1536` | Размерность вектора (только HTTP; SIGLIP определяет автоматически) |
|
||||
| `AGENTIK_EMBEDDING_BACKEND` | `HTTP` | `HTTP` (POST /v1/embeddings) или `SIGLIP` (on-device, без сети) |
|
||||
| `AGENTIK_EMBEDDING_MODEL_PATH` | _только SIGLIP_ | Путь к `text_model_int8.onnx` (SigLIP2) |
|
||||
| `AGENTIK_EMBEDDING_TOKENIZER_PATH` | _только SIGLIP_ | Путь к `tokenizer.model` (sentencepiece) |
|
||||
| `AGENTIK_SOUL` | _выкл._ | Путь к `SOUL.md` — файл персоны (markdown), вставляется в начало system prompt |
|
||||
| `AGENTIK_LLM_BACKEND` | — | `openai` или `google` (см. ниже) |
|
||||
| `AGENTIK_MCP_CONFIG` | _выкл._ | Путь к JSON со списком MCP-серверов |
|
||||
| `AGENTIK_SYSTEM_PROMPT` | `be brief` | Базовый system prompt |
|
||||
| `OPENAI_CONTEXT_WINDOW` | _выкл._ | Лимит контекстного окна в токенах (для compaction'а) |
|
||||
| `AGENTIK_GOOGLE_CONTEXT_WINDOW` | _выкл._ | То же для Google backend |
|
||||
| `AGENTIK_COMPRESSION_THRESHOLD` | `0.8` | Доля лимита, при которой запускается compaction |
|
||||
| `AGENTIK_REFLECTION_INTERVAL` | `10` | Self-reflection: каждый N-й пользовательский ход агент оценивает себя (LiteLlm) и сохраняет рефлексию. `0` = выключено. |
|
||||
| `AGENTIK_REFLECTION_TOP_K` | `3` | Сколько последних рефлексий подмешивать в system prompt как «слабые места». `0` = не подмешивать. |
|
||||
| `AGENTIK_SKILL_MINING_INTERVAL` | `15` | Skill mining: через сколько user-ходов запускать фоновый прогон SkillMiner. `0` = выключено. |
|
||||
| `AGENTIK_SKILL_MINING_MAX_TURNS` | `30` | Сколько последних ходов передавать SkillMiner'у за один прогон. |
|
||||
| `AGENTIK_DEBUG_ENDPOINTS` | `0` | `1` включает debug-эндпоинты (`/debug/reflect`, `/debug/skill-mine`, `/debug/curate`, `/debug/compact`, `/debug/tokens`) |
|
||||
| `AGENTIK_AUTO_DOWNLOAD_MODEL` | `0` | `1` — при старте скачать LiteRT-LM модель в `AGENTIK_GOOGLE_MODEL_PATH` если её там нет (через `pull-model` логику). |
|
||||
| `AGENTIK_DB_PATH` | `./agentik.db` | Путь к SQLite |
|
||||
| `AGENTIK_AGENT_ID` | `agentik` | ID агента (для multi-instance) |
|
||||
| `AGENTIK_LLM_BACKEND` | `openai` | `openai` или `google` |
|
||||
| `AGENTIK_LLM_MODEL` | (выбирается по backend) | Имя модели |
|
||||
| `AGENTIK_LLM_API_URL` | `http://localhost:8001/v1` | Endpoint для OpenAI-compatible |
|
||||
| `AGENTIK_LLM_API_KEY` | `no-key-needed` | Auth header |
|
||||
| `AGENTIK_LLM_CONTEXT_TOKENS` | `115000` | Сколько токенов остаётся модели |
|
||||
| `AGENTIK_GOOGLE_MODEL_PATH` | `/root/gemma-4-E2B-it.litertlm` | Путь к `.litertlm` файлу |
|
||||
| `AGENTIK_GOOGLE_MODEL_URL` | `https://static.binom.pw/models/gemma-4-E2B-it.litertlm` | Откуда скачивать |
|
||||
| `AGENTIK_GOOGLE_MODEL_SHA256_URL` | — | Если задан — verify по SHA-256 |
|
||||
| `AGENTIK_AUTO_DOWNLOAD_MODEL` | `0` | `1` = скачать модель если её нет |
|
||||
| `AGENTIK_MEMORY_BACKEND` | `vector` | `md`, `vector` или `off` |
|
||||
| `AGENTIK_EMBEDDING_BACKEND` | `http` | `http` или `siglip` (только для `vector`) |
|
||||
| `AGENTIK_EMBEDDING_API_URL` | `http://localhost:8001/v1` | Endpoint для эмбеддингов |
|
||||
| `AGENTIK_EMBEDDING_MODEL` | `text-embedding-3-small` | Имя embedding-модели |
|
||||
| `AGENTIK_SOUL_PATH` | `~/.agentik/SOUL.md` | Путь к SOUL.md |
|
||||
| `AGENTIK_SKILLS_DIR` | `~/.agentik/skills/` | Каталог SKILL.md |
|
||||
| `AGENTIK_MEMORY_DIR` | `~/.agentik/memory/` | Каталог для md-памяти |
|
||||
| `AGENTIK_TOOLSETS_DEFAULT` | `memory,skills,files,web` | Включённые тулы |
|
||||
| `AGENTIK_DEBUG` | `0` | `1` = verbose logging |
|
||||
|
||||
### OpenAI backend
|
||||
Значения читаются через `AgentikConfig.fromEnv()` в `:standalone/.../Main.kt`.
|
||||
|
||||
| Переменная | Обязательна | Назначение |
|
||||
|---|---|---|
|
||||
| `OPENAI_BASE_URL` | да | Например, `https://api.openai.com/v1` |
|
||||
| `OPENAI_API_KEY` | да | API key |
|
||||
| `OPENAI_MODEL` | да | Имя модели (`gpt-4o-mini` и т.п.) |
|
||||
## Эндпоинты
|
||||
|
||||
### Google backend
|
||||
|
||||
| Переменная | Обязательна | Назначение |
|
||||
|---|---|---|
|
||||
| `AGENTIK_GOOGLE_MODEL_PATH` | да | Путь к `.litertlm` файлу |
|
||||
| `AGENTIK_GOOGLE_MODEL_URL` | нет | URL для скачивания (default: `https://static.binom.pw/models/gemma-4-E2B-it.litertlm`) |
|
||||
| `AGENTIK_GOOGLE_MODEL_SHA256_URL` | нет | URL с эталонным SHA-256 (если задано — файл проверяется) |
|
||||
|
||||
## Полный пример запуска
|
||||
|
||||
```bash
|
||||
export AGENTIK_PORT=8080
|
||||
export AGENTIK_DB_PATH=/var/lib/agentik/state.db
|
||||
export AGENTIK_MEMORY_DIR=/var/lib/agentik/memory
|
||||
export AGENTIK_SOUL=/etc/agentik/SOUL.md
|
||||
export AGENTIK_SKILLS_DIR=/etc/agentik/skills
|
||||
export AGENTIK_MCP_CONFIG=/etc/agentik/mcp.json
|
||||
|
||||
export AGENTIK_LLM_BACKEND=openai
|
||||
export OPENAI_BASE_URL=https://api.openai.com/v1
|
||||
export OPENAI_API_KEY=sk-…
|
||||
export OPENAI_MODEL=gpt-4o-mini
|
||||
|
||||
mkdir -p "$(dirname "$AGENTIK_DB_PATH")" \
|
||||
"$AGENTIK_MEMORY_DIR" \
|
||||
"$(dirname "$AGENTIK_SOUL")" \
|
||||
"$(dirname "$AGENTIK_MCP_CONFIG")"
|
||||
|
||||
java -jar standalone/build/libs/standalone-all.jar
|
||||
```
|
||||
|
||||
На старте выведет что-то вроде:
|
||||
|
||||
```
|
||||
agentik standalone listening on http://localhost:8080
|
||||
GET /health
|
||||
POST /agentik/conversations -> 201
|
||||
GET /agentik/conversations/{id}/events -> SSE
|
||||
storage: /var/lib/agentik/state.db
|
||||
llm: OPENAI gpt-4o-mini @ https://api.openai.com/v1
|
||||
mcp: 4 tools from 2 servers
|
||||
skills: 3 loaded from /etc/agentik/skills
|
||||
soul: /etc/agentik/SOUL.md (842 chars)
|
||||
memory: /var/lib/agentik/memory (md-backend)
|
||||
compaction: enabled, threshold=0.8, window=128000 tokens
|
||||
curator: enabled (interval=1d, maxAge=90d)
|
||||
reflection: enabled (interval=10, topK=3)
|
||||
```
|
||||
|
||||
## Остановка
|
||||
|
||||
`Ctrl-C` → срабатывает shutdown hook: агент, MCP-серверы, SQLite-стора и
|
||||
LLM-клиент закрываются корректно (SQLite фиксирует WAL, MCP-процессы
|
||||
получают SIGTERM).
|
||||
|
||||
## Клиенты к :standalone
|
||||
|
||||
- `:agentik-cli` — REPL со slash-командами (`/new`, `/list`, `/interrupt` …).
|
||||
- `:agentik-tui` — Compose-style TUI, чисто клавиатурная навигация.
|
||||
| Метод | Путь | Transport | Описание |
|
||||
|---|---|---|---|
|
||||
| `GET` | `/health` | любой | health-check (`{"ok":true}`) |
|
||||
| `POST` | `/agui` | AG-UI | Стриминг run (SSE) |
|
||||
| `POST` | `/` | A2A | JSON-RPC `message/send`, `tasks/get`, `tasks/cancel` |
|
||||
| `GET` | `/.well-known/agent-card.json` | A2A | Discovery |
|
||||
| `POST` | `/agentik/conversations` | :proto | Создать диалог |
|
||||
| `GET` | `/agentik/conversations` | :proto | Список диалогов |
|
||||
| `GET` | `/agentik/conversations/:id` | :proto | Snapshot |
|
||||
| `GET` | `/agentik/conversations/:id/messages` | :proto | История |
|
||||
| `POST` | `/agentik/conversations/:id/send` | :proto | Send (SSE) |
|
||||
| `GET` | `/agentik/conversations/:id/events` | :proto | Live-events (SSE) |
|
||||
| `POST` | `/agentik/conversations/:id/interrupt` | :proto | Прервать |
|
||||
| `POST` | `/agentik/conversations/:id/rename` | :proto | Переименовать |
|
||||
| `DELETE` | `/agentik/conversations/:id` | :proto | Удалить |
|
||||
|
||||
## Тесты
|
||||
|
||||
```bash
|
||||
./gradlew :standalone:jvmTest
|
||||
```
|
||||
./gradlew :standalone:jvmTest # unit-тесты
|
||||
./gradlew :standalone:integrationTest # integration (Testcontainers)
|
||||
./gradlew :standalone:shadowJar # → build/libs/agentik-0.1.0-all.jar
|
||||
```
|
||||
|
||||
## Известные ограничения
|
||||
|
||||
1. **vLLM не поддерживает cancel-inference** (`interrupt()` только
|
||||
закрывает client SSE-socket; бэкенд всё равно генерирует до конца).
|
||||
2. **A2A JSON discriminator — `"kind"`** (text/file/data),
|
||||
а не `"type"`. См. `A2aJson` в `:standalone`.
|
||||
3. **SSE в не-TTY ssh закрывается на default Ktor timeout**.
|
||||
|
||||
## Текущий статус
|
||||
|
||||
Production-ready. Все KMP-модули проекта интегрированы. Полный
|
||||
manual-test checklist смотрите в [`MANUAL-TESTS.md`](../../MANUAL-TESTS.md)
|
||||
или `MANUAL-TESTS.md` в корне.
|
||||
|
||||
## Где скачать
|
||||
|
||||
- **Source**: `git clone https://git.binom.pw/subochev/agentik`
|
||||
- **Fatjar**: Gitea CI artifacts (через `.gitea/workflows/release.yml`
|
||||
на tag `v*`) или собирается через `./gradlew :standalone:shadowJar`.
|
||||
|
||||
## Версии
|
||||
|
||||
Все `gradle/libs.versions.toml`. Поднять версию → release через
|
||||
`git tag v0.2.0 && git push --tags` → CI собирает все KMP-таргеты
|
||||
публикует артефакты.
|
||||
|
||||
@@ -12,6 +12,13 @@ plugins {
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
// CI-флаг: при -PskipVectorMemory=true :memory-vector не подключается как
|
||||
// зависимость — нужно для CI runner'а (text-embedding-kmp ещё не опубликован
|
||||
// в caffeine). Подробнее см. memory-vector/build.gradle.kts.
|
||||
val skipVectorMemory: Boolean =
|
||||
(project.findProperty("skipVectorMemory") == "true") ||
|
||||
System.getenv("SKIP_VECTOR_MEMORY") == "1"
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
|
||||
@@ -46,7 +53,9 @@ kotlin {
|
||||
// Долговременная память (Hermes-style MD-бэкенд) + хранилище истории.
|
||||
implementation(project(":memory-api"))
|
||||
implementation(project(":memory-md"))
|
||||
implementation(project(":memory-vector"))
|
||||
if (!skipVectorMemory) {
|
||||
implementation(project(":memory-vector"))
|
||||
}
|
||||
implementation(project(":storage-core"))
|
||||
implementation(project(":storage-sqlite"))
|
||||
implementation(project(":agent-toolsets"))
|
||||
|
||||
Reference in New Issue
Block a user