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:
+59
-43
@@ -1,62 +1,78 @@
|
||||
# :storage-sqlite — `pw.binom.agentik.storage.sqlite`
|
||||
# `:storage-sqlite` — SQLite реализация `:storage-core` (JVM-only)
|
||||
|
||||
**SQLDelight-реализация всех 4 сторов из `:storage-core` поверх SQLite.**
|
||||
JVM-only (SQLDelight пока не публикует KMP-драйверы за пределами JVM/Android).
|
||||
## Что что это
|
||||
|
||||
## Какую проблему решает
|
||||
Production persistence для `:standalone` на [SQLDelight](https://cashapp.github.io/sqldelight/):
|
||||
|
||||
Прод-запуск `:standalone` должен переживать рестарт. In-memory не подходит —
|
||||
нужна **реальная БД**. SQLite выбран потому что:
|
||||
- **messages** — append-only журнал с `conversation_id`, `created_at`.
|
||||
- **working_memory** — rolling buffer последних 100 entries, типы
|
||||
в JSON (`UserMessage / AssistantMessage / ToolExchange / SystemPrompt`).
|
||||
- **conversations** — метаданные (id, title, model, timestamps).
|
||||
- **reflections** — произвольные заметки ("I notice you often
|
||||
prefer short replies").
|
||||
- Промпт хранителя (`@mem0`) индексирован отдельно для быстрого
|
||||
доступа.
|
||||
|
||||
- **Один файл** (`AGENTIK_DB_PATH`) — легко бэкапить, переносить, инспектить.
|
||||
- **WAL** — запись не блокирует чтение; диалоги не фризят при compaction.
|
||||
- **Без отдельного сервиса** — в отличие от PostgreSQL/MySQL не нужно ничего
|
||||
поднимать рядом.
|
||||
Решает: стабильная, локальная, нулевая-настройка БД. Подходит и для
|
||||
desktop-продакшена, и для Android, и для тестов (через Testcontainers).
|
||||
|
||||
## Схема
|
||||
## Где используется
|
||||
|
||||
SQLDelight `.sq`-файлы в `src/main/sqldelight/`:
|
||||
- `:standalone` подключает по умолчанию (`storage.db` = путь из
|
||||
`AGENTIK_DB_PATH`).
|
||||
|
||||
- `Conversation.sq` — `conversations` (id, title, created_at, updated_at, is_temporal)
|
||||
- `Message.sq` — `messages` (id, conversation_id, role, content, working_memory_index, date)
|
||||
- `WorkingMemory.sq` — `working_memory` (id, conversation_id, entry_kind, payload_json, index, instant)
|
||||
- `Reflection.sq` — `reflection` (id, conversation_id, score, weak_points_json, created_at)
|
||||
|
||||
`SqliteStores` (фасад) собирает все 4 стора в `StorageBundle` поверх общего
|
||||
SQLite-driver. Каждый store — отдельный класс, с тред-безопасностью через
|
||||
`Mutex` на запись.
|
||||
|
||||
## Подключение
|
||||
## Как подключить
|
||||
|
||||
```kotlin
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
alias(libs.plugins.sqldelight)
|
||||
jvmMain.dependencies {
|
||||
implementation("pw.binom.agentik:storage-sqlite:0.1.0")
|
||||
implementation("pw.binom.agentik:storage-core:0.1.0")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("pw.binom.agentik:storage-sqlite:$version")
|
||||
// Транзитивно: :storage-core + sqldelight-runtime/coroutines + sqlite-driver
|
||||
}
|
||||
|
||||
// Использование
|
||||
val driver = JdbcSqliteDriver("jdbc:sqlite:agentik.db")
|
||||
SqliteStores.Schema.migrate(driver) // CREATE TABLE IF NOT EXISTS + ALTER
|
||||
val bundle = SqliteStores.fromDriver(driver, clock = Clock.System)
|
||||
val storage = SqliteStorageSystem.open(Path("agentik.db"))
|
||||
val messages: MessageStore = storage.messages
|
||||
```
|
||||
|
||||
`:standalone` инициализирует бэкенд автоматически по `AGENTIK_DB_PATH`.
|
||||
## Версии
|
||||
|
||||
## Где смотреть версии
|
||||
`gradle/libs.versions.toml` → `[versions] agentik-storage-sqlite`.
|
||||
|
||||
- `version` из `gradle.properties` (`version=0.1.0`)
|
||||
- релизы: `https://git.binom.pw/subochev/agentik/releases`
|
||||
Зависит от `app.cash.sqldelight:sqlite-driver:2.1.0` (через
|
||||
`gradle/libs.versions.toml`).
|
||||
|
||||
## Сборка
|
||||
## Тесты
|
||||
|
||||
```bash
|
||||
./gradlew :storage-sqlite:build
|
||||
```
|
||||
./gradlew :storage-sqlite:jvmTest
|
||||
```
|
||||
|
||||
JVM-only. Тянет `:storage-core` + `app.cash.sqldelight:runtime` +
|
||||
`app.cash.sqldelight:coroutines-extensions` + `app.cash.sqldelight:sqlite-driver`.
|
||||
Покрывают: миграции (через `migrations/` каталог и SQLDelight
|
||||
`*.sqm`), round-trip, race-conditions (concurrent append), paged
|
||||
flow.
|
||||
|
||||
## Что в схеме (упрощённо)
|
||||
|
||||
```sql
|
||||
CREATE TABLE messages (
|
||||
id TEXT PRIMARY KEY,
|
||||
conversation_id TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL, -- ISO Instant
|
||||
kind TEXT NOT NULL, -- 'user', 'assistant', 'tool_call', 'tool_result'
|
||||
body_json TEXT NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_messages_conv_time ON messages(conversation_id, created_at);
|
||||
|
||||
CREATE TABLE working_memory (
|
||||
conversation_id TEXT NOT NULL,
|
||||
entry_id TEXT PRIMARY KEY,
|
||||
created_at TEXT NOT NULL,
|
||||
kind TEXT NOT NULL,
|
||||
body_json TEXT NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
Полная схема + миграции — в `src/jvmMain/sqldelight/`.
|
||||
|
||||
## Текущий статус
|
||||
|
||||
Используется продакшеном. Миграции 1.0+.
|
||||
|
||||
Reference in New Issue
Block a user