docs: per-module README + root navigation hub + CI/release workflows
ci / JVM build + tests (push) Failing after 1m57s

- README.md в каждом подмодуле: для библиотек — описание проблемы,
  подключение через maven-central/caffeine, версии в gradle/libs.versions.toml.
  Для запускаемых модулей — команды запуска + переменные среды с дефолтами.
- Корневой README.md переписан как навигационный хаб: что это, где клиенты,
  где серверы, как собрать, как опубликовать.
- build.gradle.kts: per-module POM-description через единую карту в rootProject.extra
  (порядок важен — нужно ДО apply плагина KMP, поэтому beforeEvaluate в subprojects).
- .gitea/workflows/ci.yml (новый): build + jvmTest + shadowJar на PR/push main.
- .gitea/workflows/release.yml (обновлён): публикует библиотеки в caffeine
  Nexus + собирает 3 fatjar'а и крепит их к release как бинарные ассеты.
This commit is contained in:
2026-09-16 16:24:03 +03:00
parent e68db11aaa
commit 0fdc12695e
18 changed files with 1279 additions and 364 deletions
+77
View File
@@ -0,0 +1,77 @@
# :storage-core — `pw.binom.agentik.storage`
**Интерфейсы хранилища разговорной истории агента: `ConversationStore`,
`MessageStore`, `WorkingMemoryStore`, `ReflectionStore`.**
Без зависимостей от конкретной БД.
## Какую проблему решает
`:standalone` нужно сохранять диалоги между перезапусками, держать working
memory (сжатую историю, которую видит LLM), reflection-записи. Но привязываться
к конкретной БД (SQLite) в контракте нельзя — для Android подходит другая
история, для тестов — in-memory, для экспериментов с Postgres — третья.
`:storage-core` отделяет **что хранить** (контракт) от **где хранить**
(бэкенды — `:storage-sqlite`, `:storage-inmemory`, и в будущем `:storage-android`).
Агрегатор `StorageBundle` собирает все 4 стора разом.
## Что в контракте
```kotlin
interface ConversationStore : AutoCloseable {
suspend fun upsert(c: Conversation)
suspend fun get(id: String): Conversation?
suspend fun list(offset, limit, orderBy): List<Conversation>
suspend fun delete(id: String): Boolean
fun events(after: Instant): Flow<ConversationStoreEvent>
}
interface MessageStore : AutoCloseable {
suspend fun append(message: Message, conversationId: String, workingMemoryIndex: Int?)
suspend fun listByConversation(conversationId: String, after: Instant?, offset, limit): List<Message>
suspend fun update(message: Message, conversationId: String) // правка + бамп updatedAt
suspend fun deleteByConversation(conversationId: String)
}
interface WorkingMemoryStore : AutoCloseable {
suspend fun append(conversationId: String, entry: WorkingMemoryEntry, index: Int)
suspend fun listByConversation(conversationId: String, after: Instant?): List<WorkingMemoryEntry>
suspend fun compact(conversationId: String, fromIndex: Int, summary: SummaryEntry)
suspend fun reset(conversationId: String)
}
interface ReflectionStore : AutoCloseable {
suspend fun append(conversationId: String, reflection: ReflectionEntry)
suspend fun recent(conversationId: String?, topK: Int): List<ReflectionEntry>
}
```
`WorkingMemoryEntry` — `sealed interface`: `User`, `Assistant`, `ToolExchange`,
`Summary`. Каждый entry имеет `instant` (когда попал в working memory) и
`index` (порядковый номер для восстановления при компакции).
## Подключение
```kotlin
commonMain {
implementation("pw.binom.agentik:storage-core:$version")
// + бэкенд:
implementation("pw.binom.agentik:storage-inmemory:$version") // тесты
// или
implementation("pw.binom.agentik:storage-sqlite:$version") // прод
}
```
## Где смотреть версии
- `version` из `gradle.properties` (`version=0.1.0`)
- релизы: `https://git.binom.pw/subochev/agentik/releases`
## Сборка
```bash
./gradlew :storage-core:build
```
KMP-таргеты — полный набор. Зависимости — только `kotlinx-coroutines` +
`kotlinx-serialization`.