Files
agentik/storage-core
subochev 0fdc12695e
ci / JVM build + tests (push) Failing after 1m57s
docs: per-module README + root navigation hub + CI/release workflows
- 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 как бинарные ассеты.
2026-09-16 16:24:03 +03:00
..

: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 стора разом.

Что в контракте

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 (порядковый номер для восстановления при компакции).

Подключение

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

Сборка

./gradlew :storage-core:build

KMP-таргеты — полный набор. Зависимости — только kotlinx-coroutines + kotlinx-serialization.