From 2d9ad526bbe006f7d467706d3a64596788d5ca8e Mon Sep 17 00:00:00 2001 From: subochev Date: Sun, 20 Sep 2026 15:02:54 +0300 Subject: [PATCH] refactor(storage): split :storage-core into message-store-api + working-memory-api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Разделяет монолитный :storage-core на 3 модуля с чёткими границами: :message-store-api — MessageStore, ReflectionStore, EventStore, ConversationStore + Content, Payload, MessageContext, Ids, MessageEvent (audit log + event stream) :working-memory-api — WorkingMemoryStore + WorkingMemoryEntry (runtime context с compaction) :storage-bundle — StorageBundle агрегатор, зависит от обоих (только для server-side runtime) Пакеты: pw.binom.agentik.storage.* → УДАЛЕНО pw.binom.agentik.messageStore.* — append-only API pw.binom.agentik.messageStore.events.* — EventStore + EventRecord pw.binom.agentik.workingMemory.* — WM API pw.binom.agentik.storageBundle.* — aggregator Зачем: - Тонкий клиент может подтянуть ТОЛЬКО :message-store-api (~15KB, нет compaction-логики, нет MessageStore+WorkingMemoryStore cross-deps). - Android-agent в будущем подключит :message-store-api для audit log, серверный runtime — :storage-bundle со всем. - Компиляционные границы защищают от случайной зависимости от WM в read-only клиентах (раньше один :storage-core не давал такой гарантии). Миграция: - Имплементации (:storage-inmemory, :storage-sqlite, :storage-ksqlite) обновили package + добавили deps на оба API модуля + :storage-bundle. - Тесты из :storage-core (PersistenceTest, SqliteStoresMigrationTest, TokenStatsTest) переехали в :standalone, получили testImplementation на оба API модуля и импорты новых типов. - 52 файла в :standalone, :agent-toolsets, :llm-tools, :server, :client, :agentik-cli обновили FQN. - :storage-core удалён. Совместимость схем не меняется — все 5 impl'ов (3 backend × 5 store) хранят данные в тех же таблицах, миграция между Sqlite и Ksqlite возможна через SQL dump. Тесты: standalone 178 ✅ agent-toolsets 36 ✅ storage-inmemory 47 ✅ storage-sqlite 17 ✅ (включая переехавшие persistence/* + tokenStats) storage-ksqlite 36 ✅ --- Total: 314 tests, 0 failures --- agent-toolsets/build.gradle.kts | 4 +- .../pw/binom/agentik/client/AgentClient.kt | 2 +- llm-tools/build.gradle.kts | 3 +- .../agentik/llm/tools/LlmMemoryReviewer.kt | 2 +- .../binom/agentik/llm/tools/LlmReflector.kt | 4 +- message-store-api/build.gradle.kts | 33 ++++++++ .../pw/binom/agentik/messageStore}/Content.kt | 2 +- .../messageStore}/ConversationRecord.kt | 2 +- .../messageStore}/ConversationStore.kt | 2 +- .../pw/binom/agentik/messageStore}/Ids.kt | 2 +- .../agentik/messageStore}/MessageContext.kt | 2 +- .../agentik/messageStore}/MessageRecord.kt | 2 +- .../agentik/messageStore}/MessageStore.kt | 2 +- .../pw/binom/agentik/messageStore}/Payload.kt | 2 +- .../agentik/messageStore}/ReflectionStore.kt | 2 +- .../messageStore}/events/EventStore.kt | 2 +- server/build.gradle.kts | 3 +- .../kotlin/pw/binom/agentik/server/Module.kt | 2 +- .../kotlin/pw/binom/agentik/server/Routes.kt | 2 +- settings.gradle.kts | 8 +- standalone/build.gradle.kts | 4 +- .../binom/agentik/standalone/DebugRoutes.kt | 14 ++-- .../pw/binom/agentik/standalone/Main.kt | 2 +- .../standalone/agent/BackgroundScheduler.kt | 8 +- .../agentik/standalone/agent/ChatAgent.kt | 18 ++--- .../standalone/agent/CompactionCoordinator.kt | 8 +- .../standalone/agent/ContextBuilder.kt | 4 +- .../standalone/agent/ConversationEvents.kt | 8 +- .../standalone/agent/ConversationLoop.kt | 26 +++--- .../standalone/agent/ConversationState.kt | 2 +- .../standalone/agent/ToolDispatcher.kt | 6 +- .../agent/ChatAgentReflectionTest.kt | 2 +- .../agentik/standalone/agent/ChatAgentTest.kt | 28 +++---- .../standalone/agent/ChatAgentToolsetsTest.kt | 2 +- .../standalone/agent/CompactionTest.kt | 14 ++-- .../standalone/agent/ContextPrefixTest.kt | 8 +- .../standalone/agent/MemoryWiringTest.kt | 2 +- .../persistence}/PersistenceTest.kt | 8 +- .../persistence}/SqliteStoresMigrationTest.kt | 7 +- .../standalone/persistence/TokenStatsTest.kt | 12 ++- storage-bundle/build.gradle.kts | 24 ++++++ .../agentik/storageBundle/StorageBundle.kt | 42 ++++++++++ storage-core/README.md | 77 ------------------ .../pw/binom/agentik/storage/StorageBundle.kt | 36 --------- .../pw/binom/agentik/storage/PayloadTest.kt | 81 ------------------- storage-inmemory/build.gradle.kts | 4 +- .../inmemory/InMemoryConversationStore.kt | 4 +- .../storage/inmemory/InMemoryEventStore.kt | 6 +- .../storage/inmemory/InMemoryMessageStore.kt | 8 +- .../inmemory/InMemoryReflectionStore.kt | 6 +- .../storage/inmemory/InMemoryStorage.kt | 2 +- .../inmemory/InMemoryWorkingMemoryStore.kt | 8 +- .../inmemory/InMemoryConversationStoreTest.kt | 2 +- .../inmemory/InMemoryEventStoreTest.kt | 4 +- .../inmemory/InMemoryMessageStoreTest.kt | 10 +-- .../inmemory/InMemoryReflectionStoreTest.kt | 4 +- .../InMemoryWorkingMemoryStoreTest.kt | 4 +- storage-ksqlite/build.gradle.kts | 4 +- .../ksqlite/KsqliteConversationStore.kt | 4 +- .../storage/ksqlite/KsqliteEventStore.kt | 6 +- .../storage/ksqlite/KsqliteMessageStore.kt | 10 +-- .../storage/ksqlite/KsqliteReflectionStore.kt | 6 +- .../agentik/storage/ksqlite/KsqliteStores.kt | 12 +-- .../ksqlite/KsqliteWorkingMemoryStore.kt | 8 +- .../agentik/storage/ksqlite/MessageCodecs.kt | 6 +- .../ksqlite/KsqliteConversationStoreTest.kt | 2 +- .../storage/ksqlite/KsqliteEventStoreTest.kt | 4 +- .../ksqlite/KsqliteMessageStoreTest.kt | 8 +- .../ksqlite/KsqliteReflectionStoreTest.kt | 2 +- .../ksqlite/KsqliteWorkingMemoryStoreTest.kt | 4 +- storage-sqlite/build.gradle.kts | 4 +- .../storage/sqlite/SqliteConversationStore.kt | 4 +- .../storage/sqlite/SqliteEventStore.kt | 6 +- .../storage/sqlite/SqliteMessageStore.kt | 10 +-- .../storage/sqlite/SqliteReflectionStore.kt | 6 +- .../agentik/storage/sqlite/SqliteStores.kt | 12 +-- .../sqlite/SqliteWorkingMemoryStore.kt | 8 +- .../storage/sqlite/ReflectionStoreTest.kt | 4 +- .../storage/sqlite/SqliteEventStoreTest.kt | 4 +- .../build.gradle.kts | 16 ++-- .../workingMemory}/WorkingMemoryEntry.kt | 4 +- .../workingMemory}/WorkingMemoryStore.kt | 2 +- 82 files changed, 341 insertions(+), 403 deletions(-) create mode 100644 message-store-api/build.gradle.kts rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore}/Content.kt (96%) rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore}/ConversationRecord.kt (88%) rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore}/ConversationStore.kt (96%) rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore}/Ids.kt (93%) rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore}/MessageContext.kt (97%) rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore}/MessageRecord.kt (99%) rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore}/MessageStore.kt (98%) rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore}/Payload.kt (98%) rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore}/ReflectionStore.kt (98%) rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore}/events/EventStore.kt (99%) rename standalone/src/jvmTest/kotlin/pw/binom/agentik/{storage => standalone/persistence}/PersistenceTest.kt (97%) rename standalone/src/jvmTest/kotlin/pw/binom/agentik/{storage => standalone/persistence}/SqliteStoresMigrationTest.kt (82%) create mode 100644 storage-bundle/build.gradle.kts create mode 100644 storage-bundle/src/commonMain/kotlin/pw/binom/agentik/storageBundle/StorageBundle.kt delete mode 100644 storage-core/README.md delete mode 100644 storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/StorageBundle.kt delete mode 100644 storage-core/src/commonTest/kotlin/pw/binom/agentik/storage/PayloadTest.kt rename {storage-core => working-memory-api}/build.gradle.kts (54%) rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => working-memory-api/src/commonMain/kotlin/pw/binom/agentik/workingMemory}/WorkingMemoryEntry.kt (96%) rename {storage-core/src/commonMain/kotlin/pw/binom/agentik/storage => working-memory-api/src/commonMain/kotlin/pw/binom/agentik/workingMemory}/WorkingMemoryStore.kt (98%) diff --git a/agent-toolsets/build.gradle.kts b/agent-toolsets/build.gradle.kts index 12f1ef5..e110d07 100644 --- a/agent-toolsets/build.gradle.kts +++ b/agent-toolsets/build.gradle.kts @@ -21,8 +21,8 @@ kotlin { sourceSets { commonMain.dependencies { - // :storage-core — для StorageBundle в ToolsetContext (commit 5+) - api(project(":storage-core")) + api(project(":storage-bundle")) + // :storage-bundle transitively подтягивает :message-store-api и :working-memory-api. // litert-kmp: LiteTool интерфейс (sync describe/invoke) api(libs.litert.api) diff --git a/client/src/commonMain/kotlin/pw/binom/agentik/client/AgentClient.kt b/client/src/commonMain/kotlin/pw/binom/agentik/client/AgentClient.kt index be49b3f..41ffd1c 100644 --- a/client/src/commonMain/kotlin/pw/binom/agentik/client/AgentClient.kt +++ b/client/src/commonMain/kotlin/pw/binom/agentik/client/AgentClient.kt @@ -136,7 +136,7 @@ internal class AgentClient( /** * Запись event'а, которую возвращает /events/replay endpoint. * - * Это **мини-зеркало** `pw.binom.agentik.storage.events.EventRecord` — клиент + * Это **мини-зеркало** `pw.binom.agentik.messageStore.events.EventRecord` — клиент * не зависит от `:storage-core`, поэтому определяет свою модель (wire-only). * * Формат полностью совместим с сервером — `agentikJson.encodeToString(...)` там diff --git a/llm-tools/build.gradle.kts b/llm-tools/build.gradle.kts index f2bd0d7..5f0ae86 100644 --- a/llm-tools/build.gradle.kts +++ b/llm-tools/build.gradle.kts @@ -19,7 +19,8 @@ kotlin { sourceSets { commonMain.dependencies { api(project(":memory-api")) - api(project(":storage-core")) + api(project(":message-store-api")) + api(project(":working-memory-api")) api(project(":skills")) api(libs.litert.api) implementation(libs.kotlinx.coroutines.core) diff --git a/llm-tools/src/commonMain/kotlin/pw/binom/agentik/llm/tools/LlmMemoryReviewer.kt b/llm-tools/src/commonMain/kotlin/pw/binom/agentik/llm/tools/LlmMemoryReviewer.kt index 3e6372c..d8d6734 100644 --- a/llm-tools/src/commonMain/kotlin/pw/binom/agentik/llm/tools/LlmMemoryReviewer.kt +++ b/llm-tools/src/commonMain/kotlin/pw/binom/agentik/llm/tools/LlmMemoryReviewer.kt @@ -10,7 +10,7 @@ import pw.binom.agentik.memory.MemoryStore import pw.binom.agentik.memory.MemoryStoreEvent import pw.binom.agentik.memory.NewMemoryNote import pw.binom.agentik.memory.ReviewedTurn -import pw.binom.agentik.storage.Ids +import pw.binom.agentik.messageStore.Ids import pw.binom.litert.LiteLlm import kotlin.time.Clock import kotlin.time.Instant diff --git a/llm-tools/src/commonMain/kotlin/pw/binom/agentik/llm/tools/LlmReflector.kt b/llm-tools/src/commonMain/kotlin/pw/binom/agentik/llm/tools/LlmReflector.kt index 53dd57b..023cd82 100644 --- a/llm-tools/src/commonMain/kotlin/pw/binom/agentik/llm/tools/LlmReflector.kt +++ b/llm-tools/src/commonMain/kotlin/pw/binom/agentik/llm/tools/LlmReflector.kt @@ -5,8 +5,8 @@ import kotlinx.coroutines.withContext import pw.binom.agentik.memory.ConversationTurn import pw.binom.litert.LiteConversationConfig import pw.binom.litert.LiteLlm -import pw.binom.agentik.storage.Ids -import pw.binom.agentik.storage.Reflection +import pw.binom.agentik.messageStore.Ids +import pw.binom.agentik.messageStore.Reflection import kotlin.time.Clock /** diff --git a/message-store-api/build.gradle.kts b/message-store-api/build.gradle.kts new file mode 100644 index 0000000..93dcf68 --- /dev/null +++ b/message-store-api/build.gradle.kts @@ -0,0 +1,33 @@ +plugins { + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.kotlin.serialization) +} + +// Public API для append-only storage агента (audit log, replay-after-disconnect, +// conversation metadata). Этот модуль НЕ содержит working memory — он для +// тонких клиентов, которые хотят только события/сообщения без тяжёлой +// runtime-логики. +// +// Зависимости: +// - kotlinx.coroutines / serialization (KMP). +// - БЕЗ :storage-core — мы его полностью выпиливаем, интерфейсы переезжают сюда. + +kotlin { + jvmToolchain(21) + + jvm() + linuxX64() + mingwX64() + + sourceSets { + commonMain.dependencies { + api(libs.kotlinx.coroutines.core) + api(libs.kotlinx.serialization.core) + api(libs.kotlinx.serialization.json) + } + commonTest.dependencies { + implementation(kotlin("test")) + implementation(libs.kotlinx.coroutines.test) + } + } +} diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/Content.kt b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/Content.kt similarity index 96% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/Content.kt rename to message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/Content.kt index d10125d..7bf717b 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/Content.kt +++ b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/Content.kt @@ -1,4 +1,4 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.messageStore import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/ConversationRecord.kt b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/ConversationRecord.kt similarity index 88% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/ConversationRecord.kt rename to message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/ConversationRecord.kt index 946683e..c365010 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/ConversationRecord.kt +++ b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/ConversationRecord.kt @@ -1,4 +1,4 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.messageStore import kotlin.time.Instant diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/ConversationStore.kt b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/ConversationStore.kt similarity index 96% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/ConversationStore.kt rename to message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/ConversationStore.kt index 57b82db..b5a2946 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/ConversationStore.kt +++ b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/ConversationStore.kt @@ -1,4 +1,4 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.messageStore import kotlin.time.Instant diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/Ids.kt b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/Ids.kt similarity index 93% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/Ids.kt rename to message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/Ids.kt index be49ca6..741ec17 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/Ids.kt +++ b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/Ids.kt @@ -1,4 +1,4 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.messageStore import kotlin.uuid.Uuid diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/MessageContext.kt b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/MessageContext.kt similarity index 97% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/MessageContext.kt rename to message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/MessageContext.kt index 86e6bf7..c47651a 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/MessageContext.kt +++ b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/MessageContext.kt @@ -1,4 +1,4 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.messageStore import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/MessageRecord.kt b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/MessageRecord.kt similarity index 99% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/MessageRecord.kt rename to message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/MessageRecord.kt index de66330..bccd49f 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/MessageRecord.kt +++ b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/MessageRecord.kt @@ -1,4 +1,4 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.messageStore import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/MessageStore.kt b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/MessageStore.kt similarity index 98% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/MessageStore.kt rename to message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/MessageStore.kt index 0b70300..f11e981 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/MessageStore.kt +++ b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/MessageStore.kt @@ -1,4 +1,4 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.messageStore import kotlinx.coroutines.flow.Flow import kotlin.time.Instant diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/Payload.kt b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/Payload.kt similarity index 98% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/Payload.kt rename to message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/Payload.kt index 2531ad4..164d75d 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/Payload.kt +++ b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/Payload.kt @@ -1,4 +1,4 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.messageStore import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/ReflectionStore.kt b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/ReflectionStore.kt similarity index 98% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/ReflectionStore.kt rename to message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/ReflectionStore.kt index da2c6a1..ad3a0f8 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/ReflectionStore.kt +++ b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/ReflectionStore.kt @@ -1,4 +1,4 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.messageStore import kotlinx.coroutines.flow.Flow import kotlin.time.Instant diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/events/EventStore.kt b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/events/EventStore.kt similarity index 99% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/events/EventStore.kt rename to message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/events/EventStore.kt index 2465bf5..2caa695 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/events/EventStore.kt +++ b/message-store-api/src/commonMain/kotlin/pw/binom/agentik/messageStore/events/EventStore.kt @@ -1,4 +1,4 @@ -package pw.binom.agentik.storage.events +package pw.binom.agentik.messageStore.events import kotlinx.serialization.Serializable import kotlin.time.Instant diff --git a/server/build.gradle.kts b/server/build.gradle.kts index 7b78f36..e1bba06 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -23,7 +23,8 @@ kotlin { sourceSets { commonMain.dependencies { implementation(project(":proto")) - implementation(project(":storage-core")) + implementation(project(":message-store-api")) + implementation(project(":working-memory-api")) // Ktor (без engine — engine подключает потребитель, см. :standalone). implementation(libs.ktor.server.core) diff --git a/server/src/commonMain/kotlin/pw/binom/agentik/server/Module.kt b/server/src/commonMain/kotlin/pw/binom/agentik/server/Module.kt index 4ab26ab..9f97060 100644 --- a/server/src/commonMain/kotlin/pw/binom/agentik/server/Module.kt +++ b/server/src/commonMain/kotlin/pw/binom/agentik/server/Module.kt @@ -6,7 +6,7 @@ import io.ktor.server.plugins.contentnegotiation.ContentNegotiation import io.ktor.server.routing.Route import io.ktor.server.routing.route import pw.binom.agentik.proto.Agent -import pw.binom.agentik.storage.events.EventStore +import pw.binom.agentik.messageStore.events.EventStore /** * Встраивает HTTP/SSE-фасад протокола agentik в твой Ktor-роутинг. diff --git a/server/src/commonMain/kotlin/pw/binom/agentik/server/Routes.kt b/server/src/commonMain/kotlin/pw/binom/agentik/server/Routes.kt index 1be914d..6f901b9 100644 --- a/server/src/commonMain/kotlin/pw/binom/agentik/server/Routes.kt +++ b/server/src/commonMain/kotlin/pw/binom/agentik/server/Routes.kt @@ -25,7 +25,7 @@ import pw.binom.agentik.proto.AllEvent import pw.binom.agentik.proto.Conversation import pw.binom.agentik.proto.Content import pw.binom.agentik.proto.Event -import pw.binom.agentik.storage.events.EventStore +import pw.binom.agentik.messageStore.events.EventStore import kotlin.time.Instant internal fun Route.agentikRoutes(agent: Agent, eventStore: EventStore? = null) { diff --git a/settings.gradle.kts b/settings.gradle.kts index 186bc1e..1c1723b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -63,12 +63,14 @@ include(":memory-vector") // Интерфейсы хранилища и разговорной истории: MessageStore / WorkingMemoryStore / // ConversationStore / ReflectionStore + StorageBundle агрегатор. Реализации — // в :storage-inmemory / :storage-sqlite / :storage-android (последний deferred). -include(":storage-core") -// In-memory реализация всех 4 store'ов из :storage-core. KMP, без платформенных +// In-memory реализация store'ов из :message-store-api и :working-memory-api. KMP, // IO-зависимостей. Используется в тестах (быстрый setup, без JDBC) и будет // использоваться в Android-сборке (JVector/SQLite не подходят для ART out-of-box). +include(":message-store-api") +include(":working-memory-api") +include(":storage-bundle") include(":storage-inmemory") -// SQLDelight-реализация всех 4 store'ов из :storage-core. JVM-only (SQLDelight +// SQLDelight-реализация store'ов из :message-store-api и :working-memory-api. JVM-only // native драйверов для KMP вне JVM пока не публикует). Содержит 4 .sq-файла + // 5 классов: SqliteStores, SqliteConversationStore, SqliteMessageStore, // SqliteWorkingMemoryStore, SqliteReflectionStore. Бэкенд для прод-запуска diff --git a/standalone/build.gradle.kts b/standalone/build.gradle.kts index f7fc97b..1f227f6 100644 --- a/standalone/build.gradle.kts +++ b/standalone/build.gradle.kts @@ -32,6 +32,7 @@ kotlin { sourceSets { commonMain.dependencies { + api(project(":storage-bundle")) implementation(project(":proto")) implementation(project(":server")) @@ -56,7 +57,8 @@ kotlin { if (!skipVectorMemory) { implementation(project(":memory-vector")) } - implementation(project(":storage-core")) + implementation(project(":message-store-api")) + implementation(project(":working-memory-api")) implementation(project(":storage-sqlite")) implementation(project(":agent-toolsets")) // Generic LLM-side tools (LlmReflector, SkillMiner, LlmMemoryReviewer, diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/DebugRoutes.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/DebugRoutes.kt index de35192..57627f2 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/DebugRoutes.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/DebugRoutes.kt @@ -14,7 +14,7 @@ import pw.binom.agentik.standalone.agent.ChatConversation import pw.binom.agentik.llm.tools.LlmReflector import pw.binom.agentik.llm.tools.SkillMiner import pw.binom.agentik.standalone.agent.memory.Curator -import pw.binom.agentik.storage.StorageBundle +import pw.binom.agentik.storageBundle.StorageBundle import pw.binom.agentik.skills.SkillStore /** @@ -33,7 +33,7 @@ import pw.binom.agentik.skills.SkillStore */ internal fun Route.debugRoutes( agent: Agent, - storage: pw.binom.agentik.storage.StorageBundle, + storage: pw.binom.agentik.storageBundle.StorageBundle, reflector: LlmReflector?, skillMiner: SkillMiner?, skillStore: SkillStore?, @@ -127,14 +127,14 @@ internal fun Route.debugRoutes( * (для debug-триггеров reflector/miner; та же логика, что у хуков * [ChatConversation]). */ -internal suspend fun recentTurns(storage: pw.binom.agentik.storage.StorageBundle, conversationId: String, maxTurns: Int): List { +internal suspend fun recentTurns(storage: pw.binom.agentik.storageBundle.StorageBundle, conversationId: String, maxTurns: Int): List { val rows = storage.workingMemoryStore.list(conversationId) val pairs = mutableListOf() var pendingUser: String? = null for (row in rows) { when (val e = row.entry) { - is pw.binom.agentik.storage.WorkingMemoryEntry.User -> pendingUser = e.content.text() - is pw.binom.agentik.storage.WorkingMemoryEntry.Assistant -> { + is pw.binom.agentik.workingMemory.WorkingMemoryEntry.User -> pendingUser = e.content.text() + is pw.binom.agentik.workingMemory.WorkingMemoryEntry.Assistant -> { val user = pendingUser ?: "" pendingUser = null pairs += ConversationTurn(userMessage = user, assistantMessage = e.content.text()) @@ -146,5 +146,5 @@ internal suspend fun recentTurns(storage: pw.binom.agentik.storage.StorageBundle } /** Текстовое содержимое записей working memory (Text-контент, без картинок). */ -internal fun List.text(): String = - filterIsInstance().joinToString("\n") { it.body } +internal fun List.text(): String = + filterIsInstance().joinToString("\n") { it.body } diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/Main.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/Main.kt index 7b7403a..b9f4efd 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/Main.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/Main.kt @@ -317,7 +317,7 @@ private fun runServer() { // и interval > 0. Загружаем top-K последних рефлексий из SQLite в system prompt. val reflector: pw.binom.agentik.llm.tools.LlmReflector? = if (config.reflection.interval > 0) LlmReflector(llm = llm) else null - val recentReflections: List = + val recentReflections: List = if (config.reflection.topK > 0) kotlinx.coroutines.runBlocking { storage.reflectionStore.listRecent(config.reflection.topK) } else emptyList() diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/BackgroundScheduler.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/BackgroundScheduler.kt index a76e93f..d507949 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/BackgroundScheduler.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/BackgroundScheduler.kt @@ -12,10 +12,10 @@ import pw.binom.agentik.memory.ConversationTurn import pw.binom.agentik.memory.MemoryReviewer import pw.binom.agentik.memory.MemoryStore import pw.binom.agentik.skills.SkillStore -import pw.binom.agentik.storage.Content -import pw.binom.agentik.storage.ReflectionStore -import pw.binom.agentik.storage.WorkingMemoryEntry -import pw.binom.agentik.storage.WorkingMemoryStore +import pw.binom.agentik.messageStore.Content +import pw.binom.agentik.messageStore.ReflectionStore +import pw.binom.agentik.workingMemory.WorkingMemoryEntry +import pw.binom.agentik.workingMemory.WorkingMemoryStore import pw.binom.agentik.llm.tools.LlmReflector import pw.binom.agentik.llm.tools.SkillMiner import java.util.concurrent.atomic.AtomicLong diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ChatAgent.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ChatAgent.kt index 7bcf2e7..9b320c4 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ChatAgent.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ChatAgent.kt @@ -30,13 +30,13 @@ import pw.binom.agentik.skills.SkillCatalog import pw.binom.agentik.skills.renderSystemPromptSection import pw.binom.agentik.standalone.agent.memory.MemoryToolsFactory import pw.binom.agentik.standalone.llm.LlmConfig -import pw.binom.agentik.storage.ConversationRecord -import pw.binom.agentik.storage.Ids -import pw.binom.agentik.storage.Reflection -import pw.binom.agentik.storage.StorageBundle -import pw.binom.agentik.storage.WorkingMemoryEntry -import pw.binom.agentik.storage.events.EventRecord -import pw.binom.agentik.storage.events.EventType +import pw.binom.agentik.messageStore.ConversationRecord +import pw.binom.agentik.messageStore.Ids +import pw.binom.agentik.messageStore.Reflection +import pw.binom.agentik.storageBundle.StorageBundle +import pw.binom.agentik.workingMemory.WorkingMemoryEntry +import pw.binom.agentik.messageStore.events.EventRecord +import pw.binom.agentik.messageStore.events.EventType import pw.binom.agentik.toolsets.DisableToolsetTool import pw.binom.agentik.toolsets.EnableToolsetTool import pw.binom.agentik.toolsets.NamedTool @@ -68,7 +68,7 @@ import pw.binom.litert.LiteLlm */ class ChatAgent( override val id: String, - private val storage: pw.binom.agentik.storage.StorageBundle, + private val storage: pw.binom.agentik.storageBundle.StorageBundle, private val llm: LiteLlm, private val llmConfig: LlmConfig, private val tools: List = emptyList(), @@ -296,7 +296,7 @@ class ChatAgent( override fun createConversation(temp: Boolean): ProtoConversation { val now = now() - val id = pw.binom.agentik.storage.Ids.new("conv") + val id = pw.binom.agentik.messageStore.Ids.new("conv") val rec = ConversationRecord( id = id, title = null, diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/CompactionCoordinator.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/CompactionCoordinator.kt index a689fb8..2a3229a 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/CompactionCoordinator.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/CompactionCoordinator.kt @@ -6,10 +6,10 @@ import pw.binom.agentik.memory.ConversationTurn import pw.binom.agentik.memory.MemoryReviewer import pw.binom.agentik.memory.MemoryStore import pw.binom.agentik.standalone.agent.memory.materializeReviewNote -import pw.binom.agentik.storage.Content -import pw.binom.agentik.storage.WorkingMemoryEntry -import pw.binom.agentik.storage.WorkingMemoryRow -import pw.binom.agentik.storage.WorkingMemoryStore +import pw.binom.agentik.messageStore.Content +import pw.binom.agentik.workingMemory.WorkingMemoryEntry +import pw.binom.agentik.workingMemory.WorkingMemoryRow +import pw.binom.agentik.workingMemory.WorkingMemoryStore import pw.binom.litert.LiteContentPart import pw.binom.litert.LiteConversation import pw.binom.litert.LiteConversationConfig diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ContextBuilder.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ContextBuilder.kt index f6566ae..1528d9b 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ContextBuilder.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ContextBuilder.kt @@ -3,8 +3,8 @@ package pw.binom.agentik.standalone.agent import mu.KotlinLogging import pw.binom.agentik.memory.MemoryPrefetcher import pw.binom.litert.LiteContentPart -import pw.binom.agentik.storage.MessageContext -import pw.binom.agentik.storage.MessageOrigin +import pw.binom.agentik.messageStore.MessageContext +import pw.binom.agentik.messageStore.MessageOrigin internal class ContextBuilder( private val memoryPrefetcher: MemoryPrefetcher?, diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationEvents.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationEvents.kt index 4347d11..3ed89d1 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationEvents.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationEvents.kt @@ -8,10 +8,10 @@ import kotlinx.coroutines.launch import kotlinx.serialization.json.Json import mu.KotlinLogging import pw.binom.agentik.proto.Event as ProtoEvent -import pw.binom.agentik.storage.Ids -import pw.binom.agentik.storage.events.EventRecord -import pw.binom.agentik.storage.events.EventStore -import pw.binom.agentik.storage.events.EventType +import pw.binom.agentik.messageStore.Ids +import pw.binom.agentik.messageStore.events.EventRecord +import pw.binom.agentik.messageStore.events.EventStore +import pw.binom.agentik.messageStore.events.EventType private val log = KotlinLogging.logger {} diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationLoop.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationLoop.kt index 909820c..2571619 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationLoop.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationLoop.kt @@ -28,18 +28,18 @@ import pw.binom.agentik.proto.Event as ProtoEvent import pw.binom.agentik.proto.Message as ProtoMessage import pw.binom.agentik.proto.MessageContext as ProtoMessageContext import pw.binom.agentik.skills.SkillStore -import pw.binom.agentik.storage.Content -import pw.binom.agentik.storage.ConversationRecord -import pw.binom.agentik.storage.ConversationStore -import pw.binom.agentik.storage.MessageContext -import pw.binom.agentik.storage.MessageOrigin -import pw.binom.agentik.storage.MessageRecord -import pw.binom.agentik.storage.MessageStore -import pw.binom.agentik.storage.ReflectionStore -import pw.binom.agentik.storage.StorageBundle -import pw.binom.agentik.storage.TurnTokens -import pw.binom.agentik.storage.WorkingMemoryEntry -import pw.binom.agentik.storage.WorkingMemoryStore +import pw.binom.agentik.messageStore.Content +import pw.binom.agentik.messageStore.ConversationRecord +import pw.binom.agentik.messageStore.ConversationStore +import pw.binom.agentik.messageStore.MessageContext +import pw.binom.agentik.messageStore.MessageOrigin +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.messageStore.MessageStore +import pw.binom.agentik.messageStore.ReflectionStore +import pw.binom.agentik.storageBundle.StorageBundle +import pw.binom.agentik.messageStore.TurnTokens +import pw.binom.agentik.workingMemory.WorkingMemoryEntry +import pw.binom.agentik.workingMemory.WorkingMemoryStore import pw.binom.agentik.toolsets.ToolsetDispatchPolicy import pw.binom.litert.LiteContentPart import pw.binom.litert.LiteConversation @@ -469,7 +469,7 @@ class ConversationLoop( private fun now(): Instant = Instant.fromEpochMilliseconds(System.currentTimeMillis()) - private fun newId(prefix: String): String = pw.binom.agentik.storage.Ids.new(prefix) + private fun newId(prefix: String): String = pw.binom.agentik.messageStore.Ids.new(prefix) private fun encodeArgsJson(arguments: Map): String { val el = JsonElement.serializer() diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationState.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationState.kt index e979cf6..2aaea47 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationState.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ConversationState.kt @@ -1,7 +1,7 @@ package pw.binom.agentik.standalone.agent import kotlinx.coroutines.CoroutineScope -import pw.binom.agentik.storage.ConversationRecord +import pw.binom.agentik.messageStore.ConversationRecord import pw.binom.litert.LiteConversation import java.util.concurrent.atomic.AtomicReference import pw.binom.agentik.toolsets.NamedTool diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ToolDispatcher.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ToolDispatcher.kt index 1b23bd8..edd185b 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ToolDispatcher.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/agent/ToolDispatcher.kt @@ -5,9 +5,9 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.async import mu.KotlinLogging import pw.binom.agentik.proto.Event as ProtoEvent -import pw.binom.agentik.storage.MessageRecord -import pw.binom.agentik.storage.MessageStore -import pw.binom.agentik.storage.WorkingMemoryEntry +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.messageStore.MessageStore +import pw.binom.agentik.workingMemory.WorkingMemoryEntry import pw.binom.agentik.toolsets.ToolsetDispatchPolicy import pw.binom.litert.LiteToolCall import pw.binom.litert.LiteTool diff --git a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentReflectionTest.kt b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentReflectionTest.kt index bbd2f4e..c44b48b 100644 --- a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentReflectionTest.kt +++ b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentReflectionTest.kt @@ -5,7 +5,7 @@ import kotlin.test.assertFalse import kotlin.test.assertTrue import kotlin.time.Instant import pw.binom.agentik.skills.SkillCatalog -import pw.binom.agentik.storage.Reflection +import pw.binom.agentik.messageStore.Reflection class ChatAgentReflectionTest { diff --git a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentTest.kt b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentTest.kt index 35d6fd0..e9d7caf 100644 --- a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentTest.kt +++ b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentTest.kt @@ -14,8 +14,8 @@ import pw.binom.agentik.skills.SkillCatalog import pw.binom.agentik.skills.SkillFile import pw.binom.agentik.standalone.llm.LlmBackend import pw.binom.agentik.standalone.llm.LlmConfig -import pw.binom.agentik.storage.MessageRecord -import pw.binom.agentik.storage.WorkingMemoryEntry +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.workingMemory.WorkingMemoryEntry import pw.binom.agentik.storage.sqlite.SqliteStores import pw.binom.litert.LiteContentPart import pw.binom.litert.LiteConversation @@ -41,7 +41,7 @@ import pw.binom.agentik.toolsets.NamedTool class ChatAgentTest { - private lateinit var storage: pw.binom.agentik.storage.StorageBundle + private lateinit var storage: pw.binom.agentik.storageBundle.StorageBundle private lateinit var fakeLlm: FakeLiteLlm @BeforeTest @@ -56,7 +56,7 @@ class ChatAgentTest { } private fun newAgent( - storage: pw.binom.agentik.storage.StorageBundle = this.storage, + storage: pw.binom.agentik.storageBundle.StorageBundle = this.storage, llm: LiteLlm = this.fakeLlm, tools: List = emptyList(), skills: SkillCatalog = SkillCatalog.EMPTY, @@ -160,10 +160,10 @@ class ChatAgentTest { // добавим сообщение, чтобы потом убедиться, что каскад сработал storage.messageStore.append( - pw.binom.agentik.storage.MessageRecord.UserMessage( + pw.binom.agentik.messageStore.MessageRecord.UserMessage( id = "m1", conversationId = id, - content = listOf(pw.binom.agentik.storage.Content.Text("hi")), + content = listOf(pw.binom.agentik.messageStore.Content.Text("hi")), createdAt = Instant.fromEpochMilliseconds(1_700_000_000_000), ), ) @@ -190,11 +190,11 @@ class ChatAgentTest { // user message записан в audit + working memory val msgs = storage.messageStore.listAll(conv.id) assertEquals(2, msgs.size) - assertEquals("hi", (msgs[0] as pw.binom.agentik.storage.MessageRecord.UserMessage).content.let { - (it[0] as pw.binom.agentik.storage.Content.Text).body + assertEquals("hi", (msgs[0] as pw.binom.agentik.messageStore.MessageRecord.UserMessage).content.let { + (it[0] as pw.binom.agentik.messageStore.Content.Text).body }) - assertEquals("hello back", (msgs[1] as pw.binom.agentik.storage.MessageRecord.AssistantMessage).content.let { - (it[0] as pw.binom.agentik.storage.Content.Text).body + assertEquals("hello back", (msgs[1] as pw.binom.agentik.messageStore.MessageRecord.AssistantMessage).content.let { + (it[0] as pw.binom.agentik.messageStore.Content.Text).body }) } @@ -327,8 +327,8 @@ class ChatAgentTest { val msgs = storage.messageStore.listAll(conv.id) assertEquals(2, msgs.size) - assertIs(msgs[0]) - val err = assertIs(msgs[1]) + assertIs(msgs[0]) + val err = assertIs(msgs[1]) assertEquals("boom from llm", err.message) // backfill через getMessages (polling/reconnect) тоже видит ошибку @@ -372,7 +372,7 @@ class ChatAgentTest { // audit: только user (assistant не успел сгенериться) val msgs = storage.messageStore.listAll(conv.id) assertEquals(1, msgs.size) - assertIs(msgs[0]) + assertIs(msgs[0]) // working memory: только user (assistant skipped because пустой) val wm = storage.workingMemoryStore.list(conv.id) @@ -428,7 +428,7 @@ class ChatAgentTest { // audit: user + toolcall + toolresult (tool выполнился), assistant может быть val msgs = storage.messageStore.listAll(conv.id) - val toolResult = msgs.filterIsInstance().firstOrNull() + val toolResult = msgs.filterIsInstance().firstOrNull() assertNotNull(toolResult, "tool result должен быть в audit — tool выполнился нормально") val toolResultResult = toolResult!!.result!! assertTrue(toolResultResult.contains("echo"), "tool result содержит реальный ответ тулы: $toolResultResult") diff --git a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentToolsetsTest.kt b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentToolsetsTest.kt index 4ca8c3c..2714205 100644 --- a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentToolsetsTest.kt +++ b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ChatAgentToolsetsTest.kt @@ -39,7 +39,7 @@ class ChatAgentToolsetsTest { private fun newAgent( toolsets: List = emptyList(), - ): Pair { + ): Pair { val storage = SqliteStores.inMemory().asBundle() val agent = ChatAgent( id = "test-agent", diff --git a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/CompactionTest.kt b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/CompactionTest.kt index 79adcf0..fdadd3a 100644 --- a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/CompactionTest.kt +++ b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/CompactionTest.kt @@ -40,7 +40,7 @@ import pw.binom.agentik.llm.tools.SummaryTurn */ class CompactionTest { - private lateinit var storage: pw.binom.agentik.storage.StorageBundle + private lateinit var storage: pw.binom.agentik.storageBundle.StorageBundle private lateinit var fakeLlm: FakeLiteLlm @BeforeTest @@ -89,7 +89,7 @@ class CompactionTest { } val wm = storage.workingMemoryStore.list(conv.id) // Без compaction все ходы остаются в памяти (System + 10 user/assistant = 21 строк). - val summaries = wm.filter { it.entry is pw.binom.agentik.storage.WorkingMemoryEntry.Summary } + val summaries = wm.filter { it.entry is pw.binom.agentik.workingMemory.WorkingMemoryEntry.Summary } assertEquals(0, summaries.size, "compaction must not run without contextWindow") } @@ -101,7 +101,7 @@ class CompactionTest { conv.send(listOf(ProtoContent.Text("first"))) val wm = storage.workingMemoryStore.list(conv.id) // System + User + Assistant = 3. Без compactor — никаких Summary. - val summaries = wm.filter { it.entry is pw.binom.agentik.storage.WorkingMemoryEntry.Summary } + val summaries = wm.filter { it.entry is pw.binom.agentik.workingMemory.WorkingMemoryEntry.Summary } assertEquals(0, summaries.size, "no compaction runs without compactor") } @@ -119,10 +119,10 @@ class CompactionTest { assertTrue(compactor.calls > 0, "compactor must be called at least once when above threshold") // В working memory должна появиться Summary. val wm = storage.workingMemoryStore.list(conv.id) - val summaries = wm.filter { it.entry is pw.binom.agentik.storage.WorkingMemoryEntry.Summary } + val summaries = wm.filter { it.entry is pw.binom.agentik.workingMemory.WorkingMemoryEntry.Summary } assertTrue(summaries.isNotEmpty(), "at least one Summary entry should be present after compaction") // Summary-текст — то, что вернул наш compactor. - val summaryText = (summaries.first().entry as pw.binom.agentik.storage.WorkingMemoryEntry.Summary).text + val summaryText = (summaries.first().entry as pw.binom.agentik.workingMemory.WorkingMemoryEntry.Summary).text assertTrue(summaryText.startsWith("**Goal**"), "summary text should come from compactor: $summaryText") } @@ -162,8 +162,8 @@ class CompactionTest { // Должны быть: System + хотя бы один Summary + последние KEEP_RECENT_TURNS ходов. // KEEP_RECENT_TURNS = 4 → user/assistant последних двух ходов (third + second) могут быть не тронуты. val userAssistantCount = wm.count { - it.entry is pw.binom.agentik.storage.WorkingMemoryEntry.User || - it.entry is pw.binom.agentik.storage.WorkingMemoryEntry.Assistant + it.entry is pw.binom.agentik.workingMemory.WorkingMemoryEntry.User || + it.entry is pw.binom.agentik.workingMemory.WorkingMemoryEntry.Assistant } // Минимум 1 ход остаётся (KEEP_RECENT_TURNS). assertTrue(userAssistantCount >= 1, "at least one recent turn must be preserved") diff --git a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ContextPrefixTest.kt b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ContextPrefixTest.kt index 43fad98..8d98bbd 100644 --- a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ContextPrefixTest.kt +++ b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/ContextPrefixTest.kt @@ -1,9 +1,9 @@ package pw.binom.agentik.standalone.agent -import pw.binom.agentik.storage.MessageContext -import pw.binom.agentik.storage.MessageOrigin.EVENT -import pw.binom.agentik.storage.MessageOrigin.SYSTEM -import pw.binom.agentik.storage.MessageOrigin.USER +import pw.binom.agentik.messageStore.MessageContext +import pw.binom.agentik.messageStore.MessageOrigin.EVENT +import pw.binom.agentik.messageStore.MessageOrigin.SYSTEM +import pw.binom.agentik.messageStore.MessageOrigin.USER import pw.binom.litert.LiteContentPart import kotlin.test.Test import kotlin.test.assertEquals diff --git a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/MemoryWiringTest.kt b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/MemoryWiringTest.kt index 57ec8c8..acdddf6 100644 --- a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/MemoryWiringTest.kt +++ b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/agent/MemoryWiringTest.kt @@ -49,7 +49,7 @@ import kotlin.time.Instant */ class MemoryWiringTest { - private lateinit var storage: pw.binom.agentik.storage.StorageBundle + private lateinit var storage: pw.binom.agentik.storageBundle.StorageBundle private lateinit var fakeLlm: FakeLiteLlm private lateinit var root: Path diff --git a/standalone/src/jvmTest/kotlin/pw/binom/agentik/storage/PersistenceTest.kt b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/persistence/PersistenceTest.kt similarity index 97% rename from standalone/src/jvmTest/kotlin/pw/binom/agentik/storage/PersistenceTest.kt rename to standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/persistence/PersistenceTest.kt index 9442c15..0ad8927 100644 --- a/standalone/src/jvmTest/kotlin/pw/binom/agentik/storage/PersistenceTest.kt +++ b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/persistence/PersistenceTest.kt @@ -1,4 +1,10 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.standalone.persistence +import pw.binom.agentik.messageStore.MessageContext +import pw.binom.agentik.messageStore.MessageOrigin +import pw.binom.agentik.messageStore.ConversationRecord +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.messageStore.Content +import pw.binom.agentik.workingMemory.WorkingMemoryEntry import kotlinx.coroutines.test.runTest import pw.binom.agentik.storage.sqlite.SqliteStores diff --git a/standalone/src/jvmTest/kotlin/pw/binom/agentik/storage/SqliteStoresMigrationTest.kt b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/persistence/SqliteStoresMigrationTest.kt similarity index 82% rename from standalone/src/jvmTest/kotlin/pw/binom/agentik/storage/SqliteStoresMigrationTest.kt rename to standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/persistence/SqliteStoresMigrationTest.kt index 6ff6060..63a7f4f 100644 --- a/standalone/src/jvmTest/kotlin/pw/binom/agentik/storage/SqliteStoresMigrationTest.kt +++ b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/persistence/SqliteStoresMigrationTest.kt @@ -1,4 +1,9 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.standalone.persistence +import pw.binom.agentik.messageStore.Reflection +import pw.binom.agentik.messageStore.ConversationRecord +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.messageStore.Content +import pw.binom.agentik.workingMemory.WorkingMemoryEntry import kotlin.test.Test import kotlin.test.assertEquals diff --git a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/persistence/TokenStatsTest.kt b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/persistence/TokenStatsTest.kt index cb7def5..af6a6fd 100644 --- a/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/persistence/TokenStatsTest.kt +++ b/standalone/src/jvmTest/kotlin/pw/binom/agentik/standalone/persistence/TokenStatsTest.kt @@ -1,4 +1,14 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.standalone.persistence +import pw.binom.agentik.messageStore.TurnTokens +import pw.binom.agentik.messageStore.MessageBodyPayload +import pw.binom.agentik.messageStore.encodeBodyPayload +import pw.binom.agentik.messageStore.decodeBodyPayload +import pw.binom.agentik.messageStore.MessageContext +import pw.binom.agentik.messageStore.MessageOrigin +import pw.binom.agentik.messageStore.ConversationRecord +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.messageStore.Content +import pw.binom.agentik.workingMemory.WorkingMemoryEntry import kotlin.test.Test import kotlin.test.assertEquals diff --git a/storage-bundle/build.gradle.kts b/storage-bundle/build.gradle.kts new file mode 100644 index 0000000..a299fad --- /dev/null +++ b/storage-bundle/build.gradle.kts @@ -0,0 +1,24 @@ +plugins { + alias(libs.plugins.kotlin.multiplatform) +} + +// Агрегатор всех 5 storage-интерфейсов (MessageStore + ReflectionStore + +// EventStore + ConversationStore + WorkingMemoryStore). Зависит от обоих API +// модулей. Нужен только server-side рантайму (`:standalone`, `:agentik-cli`, +// `:agent-toolsets`, будущий `:android-agent` core). Тонкие клиенты этот модуль +// НЕ подтягивают — они работают с одним только `:message-store-api`. + +kotlin { + jvmToolchain(21) + + jvm() + linuxX64() + mingwX64() + + sourceSets { + commonMain.dependencies { + api(project(":message-store-api")) + api(project(":working-memory-api")) + } + } +} diff --git a/storage-bundle/src/commonMain/kotlin/pw/binom/agentik/storageBundle/StorageBundle.kt b/storage-bundle/src/commonMain/kotlin/pw/binom/agentik/storageBundle/StorageBundle.kt new file mode 100644 index 0000000..69b114f --- /dev/null +++ b/storage-bundle/src/commonMain/kotlin/pw/binom/agentik/storageBundle/StorageBundle.kt @@ -0,0 +1,42 @@ +package pw.binom.agentik.storageBundle + +import pw.binom.agentik.messageStore.ConversationStore +import pw.binom.agentik.messageStore.MessageStore +import pw.binom.agentik.messageStore.ReflectionStore +import pw.binom.agentik.messageStore.events.EventStore +import pw.binom.agentik.workingMemory.WorkingMemoryStore + +/** + * Агрегатор всех storage-интерфейсов для полного агент-рантайма. + * + * Зависит от **обоих** API модулей — `:message-store-api` и `:working-memory-api`. + * Тонкие клиенты, которым нужен только audit log, могут не подтягивать этот модуль + * и работать с [MessageStore] / [ReflectionStore] / [EventStore] / [ConversationStore] + * напрямую. + * + * **Реализации агрегата**: + * - [SqliteStorageBundle] — JVM-only, SQLDelight + SQLite. В `:storage-sqlite`. + * - [InMemoryStorageBundle] — KMP, Map-based. В `:storage-inmemory`. + * + * `SkillStore` НЕ входит — он в `:skills` (контент-файлы навыков), принимается + * отдельно в `ChatAgent`. + * + * AutoCloseable: один `close()` закрывает все store'ы; в реализациях без + * ресурсов (in-memory) — no-op. + */ +data class StorageBundle( + val conversationStore: ConversationStore, + val messageStore: MessageStore, + val workingMemoryStore: WorkingMemoryStore, + val reflectionStore: ReflectionStore, + val eventStore: EventStore? = null, +) : AutoCloseable { + + override fun close() { + conversationStore.close() + messageStore.close() + workingMemoryStore.close() + reflectionStore.close() + eventStore?.close() + } +} diff --git a/storage-core/README.md b/storage-core/README.md deleted file mode 100644 index 92e7e38..0000000 --- a/storage-core/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# `:storage-core` — контракт хранилища (KMP, jvm + native) - -## Что это - -Интерфейсы persistence-уровня для `:standalone`: - -- `MessageStore` — append-only история сообщений по диалогу. -- `WorkingMemoryStore` — rolling buffer текущего хода (`AssistantMessage`, - `ToolExchange`, `UserMessage`, system-prompt) для fast-recovery - при reconnect/relance. -- `ConversationStore` — метаданные диалогов (id, title, model, - timestamps). -- `ReflectionStore` — LLM-reflections (свободная форма заметок - хранителя). - -Решает: позволяет запустить агента на Android-in-memory, на -desktop-SQLite, или на production-SQLite, не переписывая логику. -Контракт минимален и async-friendly. - -## Где используется - -- `:storage-inmemory` — для тестов и Android. -- `:storage-sqlite` — прод (Desktop / server / однодесктопный - Android-development). - -## Как подключить - -```kotlin -kotlin { - sourceSets.commonMain.dependencies { - api("pw.binom.agentik:storage-core:0.1.0") - } -} -``` - -## Версии - -`gradle/libs.versions.toml` → `[versions] agentik-storage-core`. - -## Что в API - -```kotlin -interface MessageStore { - suspend fun append(conversationId: String, message: Message): Unit - suspend fun after(conversationId: String, instant: Instant, limit: Int = 100): List -} - -interface WorkingMemoryStore { - suspend fun save(conv: String, entry: WorkingMemoryEntry): Unit - fun load(conv: String): Flow // cold flow - suspend fun clear(conv: String): Unit -} - -sealed interface WorkingMemoryEntry { - val id: String - val date: Instant - class UserMessage(...) : WorkingMemoryEntry - class AssistantMessage(...) : WorkingMemoryEntry - class ToolExchange(val toolName: String, val toolArgsJson: String, val resultText: String, val wasCancelled: Boolean) : WorkingMemoryEntry - class SystemPrompt(...) : WorkingMemoryEntry -} -``` - -## Тесты - -Контрактные тесты (общие для всех имплементаций) — в `:storage-sqlite` -и `:storage-inmemory`. - -## Чего здесь НЕТ - -- Никакого HTTP / SSE. -- Никакой конкретной БД. Backend'ы в `:storage-*`. - -## Текущий статус - -Используется продакшеном. Контракт зафиксирован после -interrupt-имплементации (см. [INTERRUPT-DESIGN.md](../../docs/INTERRUPT-DESIGN.md)). diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/StorageBundle.kt b/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/StorageBundle.kt deleted file mode 100644 index d68eaba..0000000 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/StorageBundle.kt +++ /dev/null @@ -1,36 +0,0 @@ -package pw.binom.agentik.storage - -import pw.binom.agentik.storage.events.EventStore - -/** - * Агрегатор всех storage-интерфейсов, нужных агенту для работы с историей диалога. - * - * Реализации: - * - [SqliteStorageBundle] — JVM-only, основная. SQLDelight + SQLite. - * - [InMemoryStorageBundle] — Map-based, для тестов. - * - `:storage-android` — Android-специфичная (deferred, Android-сборка в планах). - * - * `SkillStore` НЕ входит сюда — он живёт в модуле `:skills` (другая ответственность: - * не сообщения/рефлексии, а контент-файлы навыков) и принимается отдельно в `ChatAgent`. - * - * [EventStore] входит начиная с commit "event-store" — для replay после - * disconnect (см. `/events/replay` endpoint в `:server`). - * - * AutoCloseable: один `close()` закрывает все store'ы. В реализациях, - * которые не владеют ресурсами (in-memory), close — no-op. - */ -data class StorageBundle( - val conversationStore: ConversationStore, - val messageStore: MessageStore, - val workingMemoryStore: WorkingMemoryStore, - val reflectionStore: ReflectionStore, - val eventStore: EventStore? = null, -) : AutoCloseable { - override fun close() { - conversationStore.close() - messageStore.close() - workingMemoryStore.close() - reflectionStore.close() - eventStore?.close() - } -} diff --git a/storage-core/src/commonTest/kotlin/pw/binom/agentik/storage/PayloadTest.kt b/storage-core/src/commonTest/kotlin/pw/binom/agentik/storage/PayloadTest.kt deleted file mode 100644 index 7b1b393..0000000 --- a/storage-core/src/commonTest/kotlin/pw/binom/agentik/storage/PayloadTest.kt +++ /dev/null @@ -1,81 +0,0 @@ -package pw.binom.agentik.storage - -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.buildJsonObject -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNull -import kotlin.test.assertTrue - -/** - * Тесты payload-формата: контекст инициации хода персистится через - * `payload_json` SQLite, старый plain-array формат читается без потерь. - */ -class PayloadTest { - - @Test - fun `user context roundtrips through MessageBodyPayload`() { - val ctx = MessageContext( - origin = MessageOrigin.USER, - description = "irc PRIVMSG", - sourceId = "irc:agentik", - ) - val encoded = encodeBodyPayload(listOf(Content.Text("hi")), ctx) - // новый формат: wrapper-объект с полем context - assertTrue(encoded.startsWith("{"), "expected wrapped object, got: $encoded") - assertTrue(encoded.contains("\"context\""), "expected context field, got: $encoded") - - val decoded = decodeBodyPayload(encoded) - assertEquals(listOf(Content.Text("hi")), decoded.content) - assertEquals(ctx, decoded.context) - } - - @Test - fun `event context roundtrips with metadata`() { - val ctx = MessageContext( - origin = MessageOrigin.EVENT, - description = "scheduled cron morning-briefing", - sourceId = "cron-42", - metadata = buildJsonObject { - put("scheduledAt", JsonPrimitive("2026-09-14T08:00:00Z")) - put("rule", JsonPrimitive("0 8 * * *")) - }, - ) - val encoded = encodeBodyPayload(listOf(Content.Text("wake up")), ctx) - val decoded = decodeBodyPayload(encoded) - assertEquals(MessageOrigin.EVENT, decoded.context?.origin) - assertEquals("scheduled cron morning-briefing", decoded.context?.description) - assertEquals("cron-42", decoded.context?.sourceId) - assertEquals("0 8 * * *", (decoded.context?.metadata?.let { (it as kotlinx.serialization.json.JsonObject)["rule"] } as? JsonPrimitive)?.content) - } - - @Test - fun `null context produces wrapper without context field`() { - val encoded = encodeBodyPayload(listOf(Content.Text("hello"))) - assertTrue(encoded.contains("\"content\""), "expected content field, got: $encoded") - val decoded = decodeBodyPayload(encoded) - assertEquals(listOf(Content.Text("hello")), decoded.content) - assertNull(decoded.context) - } - - @Test - fun `legacy plain-array payload still decodes backward compat`() { - val legacy = "[" + - """{"type":"text","body":"old message"}""" + - "]" - val decoded = decodeBodyPayload(legacy) - assertEquals(listOf(Content.Text("old message")), decoded.content) - assertNull(decoded.context) - } - - @Test - fun `system context with description only roundtrips`() { - val ctx = MessageContext(origin = MessageOrigin.SYSTEM, description = "agent startup greeting") - val encoded = encodeBodyPayload(listOf(Content.Text("boot")), ctx) - val decoded = decodeBodyPayload(encoded) - assertEquals(MessageOrigin.SYSTEM, decoded.context?.origin) - assertEquals("agent startup greeting", decoded.context?.description) - assertNull(decoded.context?.sourceId) - assertNull(decoded.context?.metadata) - } -} diff --git a/storage-inmemory/build.gradle.kts b/storage-inmemory/build.gradle.kts index 48a4c89..d19f33d 100644 --- a/storage-inmemory/build.gradle.kts +++ b/storage-inmemory/build.gradle.kts @@ -20,7 +20,9 @@ kotlin { sourceSets { commonMain.dependencies { - api(project(":storage-core")) + api(project(":message-store-api")) + api(project(":storage-bundle")) + api(project(":working-memory-api")) } commonTest.dependencies { implementation(kotlin("test")) diff --git a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryConversationStore.kt b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryConversationStore.kt index b9e3155..8eddc5f 100644 --- a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryConversationStore.kt +++ b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryConversationStore.kt @@ -3,8 +3,8 @@ package pw.binom.agentik.storage.inmemory import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlin.time.Clock -import pw.binom.agentik.storage.ConversationRecord -import pw.binom.agentik.storage.ConversationStore +import pw.binom.agentik.messageStore.ConversationRecord +import pw.binom.agentik.messageStore.ConversationStore import kotlin.time.Instant /** diff --git a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryEventStore.kt b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryEventStore.kt index 407c3ce..e114211 100644 --- a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryEventStore.kt +++ b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryEventStore.kt @@ -1,8 +1,8 @@ package pw.binom.agentik.storage.inmemory -import pw.binom.agentik.storage.events.EventRecord -import pw.binom.agentik.storage.events.EventStore -import pw.binom.agentik.storage.events.EventType +import pw.binom.agentik.messageStore.events.EventRecord +import pw.binom.agentik.messageStore.events.EventStore +import pw.binom.agentik.messageStore.events.EventType import kotlin.time.Instant import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock diff --git a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryMessageStore.kt b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryMessageStore.kt index acbcd10..444e476 100644 --- a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryMessageStore.kt +++ b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryMessageStore.kt @@ -5,10 +5,10 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import pw.binom.agentik.storage.MessageEvent -import pw.binom.agentik.storage.MessageRecord -import pw.binom.agentik.storage.MessageStore -import pw.binom.agentik.storage.TokenStats +import pw.binom.agentik.messageStore.MessageEvent +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.messageStore.MessageStore +import pw.binom.agentik.messageStore.TokenStats import kotlin.time.Instant /** diff --git a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryReflectionStore.kt b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryReflectionStore.kt index d566f78..83f2f08 100644 --- a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryReflectionStore.kt +++ b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryReflectionStore.kt @@ -5,9 +5,9 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import pw.binom.agentik.storage.Reflection -import pw.binom.agentik.storage.ReflectionEvent -import pw.binom.agentik.storage.ReflectionStore +import pw.binom.agentik.messageStore.Reflection +import pw.binom.agentik.messageStore.ReflectionEvent +import pw.binom.agentik.messageStore.ReflectionStore import kotlin.time.Instant /** diff --git a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryStorage.kt b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryStorage.kt index acb37ec..a392096 100644 --- a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryStorage.kt +++ b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryStorage.kt @@ -1,6 +1,6 @@ package pw.binom.agentik.storage.inmemory -import pw.binom.agentik.storage.StorageBundle +import pw.binom.agentik.storageBundle.StorageBundle import kotlin.time.Clock /** diff --git a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryWorkingMemoryStore.kt b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryWorkingMemoryStore.kt index de6d0c7..bc8a21a 100644 --- a/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryWorkingMemoryStore.kt +++ b/storage-inmemory/src/commonMain/kotlin/pw/binom/agentik/storage/inmemory/InMemoryWorkingMemoryStore.kt @@ -2,10 +2,10 @@ package pw.binom.agentik.storage.inmemory import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import pw.binom.agentik.storage.Ids -import pw.binom.agentik.storage.WorkingMemoryEntry -import pw.binom.agentik.storage.WorkingMemoryRow -import pw.binom.agentik.storage.WorkingMemoryStore +import pw.binom.agentik.messageStore.Ids +import pw.binom.agentik.workingMemory.WorkingMemoryEntry +import pw.binom.agentik.workingMemory.WorkingMemoryRow +import pw.binom.agentik.workingMemory.WorkingMemoryStore import kotlin.time.Instant /** diff --git a/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryConversationStoreTest.kt b/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryConversationStoreTest.kt index 00fe180..44708d4 100644 --- a/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryConversationStoreTest.kt +++ b/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryConversationStoreTest.kt @@ -1,6 +1,6 @@ package pw.binom.agentik.storage.inmemory -import pw.binom.agentik.storage.ConversationRecord +import pw.binom.agentik.messageStore.ConversationRecord import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull diff --git a/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryEventStoreTest.kt b/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryEventStoreTest.kt index 9033b53..de9c764 100644 --- a/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryEventStoreTest.kt +++ b/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryEventStoreTest.kt @@ -2,8 +2,8 @@ package pw.binom.agentik.storage.inmemory import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.test.runTest -import pw.binom.agentik.storage.events.EventRecord -import pw.binom.agentik.storage.events.EventType +import pw.binom.agentik.messageStore.events.EventRecord +import pw.binom.agentik.messageStore.events.EventType import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNull diff --git a/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryMessageStoreTest.kt b/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryMessageStoreTest.kt index eb67c12..a001994 100644 --- a/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryMessageStoreTest.kt +++ b/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryMessageStoreTest.kt @@ -1,8 +1,8 @@ package pw.binom.agentik.storage.inmemory -import pw.binom.agentik.storage.Content -import pw.binom.agentik.storage.MessageRecord -import pw.binom.agentik.storage.TurnTokens +import pw.binom.agentik.messageStore.Content +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.messageStore.TurnTokens import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNull @@ -113,8 +113,8 @@ class InMemoryMessageStoreTest { yield() // даём коллектору подписаться ДО append — иначе SharedFlow без replay потеряет эвент store.append(MessageRecord.UserMessage("u1", "c1", listOf(Content.Text("hi")), t0)) val ev = deferred.await() - assertTrue(ev is pw.binom.agentik.storage.MessageEvent.Appended) - val appended = ev as pw.binom.agentik.storage.MessageEvent.Appended + assertTrue(ev is pw.binom.agentik.messageStore.MessageEvent.Appended) + val appended = ev as pw.binom.agentik.messageStore.MessageEvent.Appended assertEquals("c1", appended.conversationId) assertEquals("u1", appended.record.id) } diff --git a/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryReflectionStoreTest.kt b/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryReflectionStoreTest.kt index b796073..b009812 100644 --- a/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryReflectionStoreTest.kt +++ b/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryReflectionStoreTest.kt @@ -1,7 +1,7 @@ package pw.binom.agentik.storage.inmemory -import pw.binom.agentik.storage.Reflection -import pw.binom.agentik.storage.ReflectionEvent +import pw.binom.agentik.messageStore.Reflection +import pw.binom.agentik.messageStore.ReflectionEvent import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull diff --git a/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryWorkingMemoryStoreTest.kt b/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryWorkingMemoryStoreTest.kt index ec17f16..763c28f 100644 --- a/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryWorkingMemoryStoreTest.kt +++ b/storage-inmemory/src/commonTest/kotlin/pw/binom/agentik/storage/inmemory/InMemoryWorkingMemoryStoreTest.kt @@ -1,7 +1,7 @@ package pw.binom.agentik.storage.inmemory -import pw.binom.agentik.storage.Content -import pw.binom.agentik.storage.WorkingMemoryEntry +import pw.binom.agentik.messageStore.Content +import pw.binom.agentik.workingMemory.WorkingMemoryEntry import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNull diff --git a/storage-ksqlite/build.gradle.kts b/storage-ksqlite/build.gradle.kts index 57302d9..d605e91 100644 --- a/storage-ksqlite/build.gradle.kts +++ b/storage-ksqlite/build.gradle.kts @@ -23,7 +23,9 @@ kotlin { sourceSets { commonMain.dependencies { - api(project(":storage-core")) + api(project(":message-store-api")) + api(project(":storage-bundle")) + api(project(":working-memory-api")) // ksqlite ещё не опубликован в Maven Central — только в локальном // caffeine-репо. Версия пока 0.1.0-SNAPSHOT (CI fallback из README). diff --git a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteConversationStore.kt b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteConversationStore.kt index ae6520a..a4f862c 100644 --- a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteConversationStore.kt +++ b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteConversationStore.kt @@ -1,8 +1,8 @@ package pw.binom.agentik.storage.ksqlite import kotlin.time.Instant -import pw.binom.agentik.storage.ConversationRecord -import pw.binom.agentik.storage.ConversationStore +import pw.binom.agentik.messageStore.ConversationRecord +import pw.binom.agentik.messageStore.ConversationStore import pw.binom.db.ksqlite.SQLiteConnection import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.sync.Mutex diff --git a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteEventStore.kt b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteEventStore.kt index 1c4995d..f91043f 100644 --- a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteEventStore.kt +++ b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteEventStore.kt @@ -1,8 +1,8 @@ package pw.binom.agentik.storage.ksqlite -import pw.binom.agentik.storage.events.EventRecord -import pw.binom.agentik.storage.events.EventStore -import pw.binom.agentik.storage.events.EventType +import pw.binom.agentik.messageStore.events.EventRecord +import pw.binom.agentik.messageStore.events.EventStore +import pw.binom.agentik.messageStore.events.EventType import pw.binom.db.ksqlite.SQLiteConnection import pw.binom.db.ksqlite.SQLitePreparedStatement import pw.binom.db.ksqlite.SQLiteResultSet diff --git a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteMessageStore.kt b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteMessageStore.kt index 6c7c6a4..7cdc1d5 100644 --- a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteMessageStore.kt +++ b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteMessageStore.kt @@ -1,11 +1,11 @@ package pw.binom.agentik.storage.ksqlite import kotlinx.serialization.json.Json -import pw.binom.agentik.storage.MessageRecord -import pw.binom.agentik.storage.MessageStore -import pw.binom.agentik.storage.TokenStats -import pw.binom.agentik.storage.decodeBodyPayload -import pw.binom.agentik.storage.encodeBodyPayload +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.messageStore.MessageStore +import pw.binom.agentik.messageStore.TokenStats +import pw.binom.agentik.messageStore.decodeBodyPayload +import pw.binom.agentik.messageStore.encodeBodyPayload import pw.binom.db.ksqlite.SQLiteConnection import pw.binom.db.ksqlite.SQLiteResultSet import kotlin.time.Instant diff --git a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteReflectionStore.kt b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteReflectionStore.kt index 4d24315..1f47383 100644 --- a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteReflectionStore.kt +++ b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteReflectionStore.kt @@ -1,8 +1,8 @@ package pw.binom.agentik.storage.ksqlite -import pw.binom.agentik.storage.Reflection -import pw.binom.agentik.storage.ReflectionEvent -import pw.binom.agentik.storage.ReflectionStore +import pw.binom.agentik.messageStore.Reflection +import pw.binom.agentik.messageStore.ReflectionEvent +import pw.binom.agentik.messageStore.ReflectionStore import pw.binom.db.ksqlite.SQLiteConnection import pw.binom.db.ksqlite.SQLiteResultSet import kotlin.time.Clock diff --git a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteStores.kt b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteStores.kt index a1ff8a8..0cdfd9a 100644 --- a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteStores.kt +++ b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteStores.kt @@ -1,11 +1,11 @@ package pw.binom.agentik.storage.ksqlite -import pw.binom.agentik.storage.ConversationStore -import pw.binom.agentik.storage.MessageStore -import pw.binom.agentik.storage.ReflectionStore -import pw.binom.agentik.storage.StorageBundle -import pw.binom.agentik.storage.WorkingMemoryStore -import pw.binom.agentik.storage.events.EventStore +import pw.binom.agentik.messageStore.ConversationStore +import pw.binom.agentik.messageStore.MessageStore +import pw.binom.agentik.messageStore.ReflectionStore +import pw.binom.agentik.storageBundle.StorageBundle +import pw.binom.agentik.workingMemory.WorkingMemoryStore +import pw.binom.agentik.messageStore.events.EventStore import pw.binom.db.ksqlite.SQLiteConnection /** diff --git a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteWorkingMemoryStore.kt b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteWorkingMemoryStore.kt index 0f44d55..ddda217 100644 --- a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteWorkingMemoryStore.kt +++ b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteWorkingMemoryStore.kt @@ -1,10 +1,10 @@ package pw.binom.agentik.storage.ksqlite import kotlinx.serialization.json.Json -import pw.binom.agentik.storage.WorkingMemoryEntry -import pw.binom.agentik.storage.WorkingMemoryRow -import pw.binom.agentik.storage.WorkingMemoryStore -import pw.binom.agentik.storage.Ids +import pw.binom.agentik.workingMemory.WorkingMemoryEntry +import pw.binom.agentik.workingMemory.WorkingMemoryRow +import pw.binom.agentik.workingMemory.WorkingMemoryStore +import pw.binom.agentik.messageStore.Ids import pw.binom.db.ksqlite.SQLiteConnection import kotlin.time.Instant import kotlinx.coroutines.Dispatchers diff --git a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/MessageCodecs.kt b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/MessageCodecs.kt index 9f81abc..fc3f54b 100644 --- a/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/MessageCodecs.kt +++ b/storage-ksqlite/src/commonMain/kotlin/pw/binom/agentik/storage/ksqlite/MessageCodecs.kt @@ -1,9 +1,9 @@ package pw.binom.agentik.storage.ksqlite import kotlinx.serialization.json.Json -import pw.binom.agentik.storage.MessageRecord -import pw.binom.agentik.storage.decodeBodyPayload -import pw.binom.agentik.storage.encodeBodyPayload +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.messageStore.decodeBodyPayload +import pw.binom.agentik.messageStore.encodeBodyPayload import pw.binom.db.ksqlite.SQLiteResultSet import kotlin.time.Instant diff --git a/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteConversationStoreTest.kt b/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteConversationStoreTest.kt index f05418b..11f7dee 100644 --- a/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteConversationStoreTest.kt +++ b/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteConversationStoreTest.kt @@ -1,7 +1,7 @@ package pw.binom.agentik.storage.ksqlite import kotlinx.coroutines.test.runTest -import pw.binom.agentik.storage.ConversationRecord +import pw.binom.agentik.messageStore.ConversationRecord import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test diff --git a/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteEventStoreTest.kt b/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteEventStoreTest.kt index c2ce19c..8fa73d2 100644 --- a/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteEventStoreTest.kt +++ b/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteEventStoreTest.kt @@ -1,8 +1,8 @@ package pw.binom.agentik.storage.ksqlite import kotlinx.coroutines.test.runTest -import pw.binom.agentik.storage.events.EventRecord -import pw.binom.agentik.storage.events.EventType +import pw.binom.agentik.messageStore.events.EventRecord +import pw.binom.agentik.messageStore.events.EventType import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test diff --git a/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteMessageStoreTest.kt b/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteMessageStoreTest.kt index b89ab28..d4967ac 100644 --- a/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteMessageStoreTest.kt +++ b/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteMessageStoreTest.kt @@ -1,9 +1,9 @@ package pw.binom.agentik.storage.ksqlite import kotlinx.coroutines.test.runTest -import pw.binom.agentik.storage.Content -import pw.binom.agentik.storage.MessageRecord -import pw.binom.agentik.storage.TurnTokens +import pw.binom.agentik.messageStore.Content +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.messageStore.TurnTokens import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test @@ -20,7 +20,7 @@ class KsqliteMessageStoreTest { stores = KsqliteStores.inMemory("msg-${kotlin.random.Random.nextLong()}") kotlinx.coroutines.runBlocking { stores.conversations.upsert( - pw.binom.agentik.storage.ConversationRecord( + pw.binom.agentik.messageStore.ConversationRecord( "conv1", null, false, Instant.parse("2026-09-15T10:00:00Z"), Instant.parse("2026-09-15T10:00:00Z"), diff --git a/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteReflectionStoreTest.kt b/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteReflectionStoreTest.kt index 89afeab..0c3a732 100644 --- a/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteReflectionStoreTest.kt +++ b/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteReflectionStoreTest.kt @@ -1,7 +1,7 @@ package pw.binom.agentik.storage.ksqlite import kotlinx.coroutines.test.runTest -import pw.binom.agentik.storage.Reflection +import pw.binom.agentik.messageStore.Reflection import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test diff --git a/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteWorkingMemoryStoreTest.kt b/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteWorkingMemoryStoreTest.kt index 190f02e..5397edb 100644 --- a/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteWorkingMemoryStoreTest.kt +++ b/storage-ksqlite/src/commonTest/kotlin/pw/binom/agentik/storage/ksqlite/KsqliteWorkingMemoryStoreTest.kt @@ -1,8 +1,8 @@ package pw.binom.agentik.storage.ksqlite import kotlinx.coroutines.test.runTest -import pw.binom.agentik.storage.Content -import pw.binom.agentik.storage.WorkingMemoryEntry +import pw.binom.agentik.messageStore.Content +import pw.binom.agentik.workingMemory.WorkingMemoryEntry import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test diff --git a/storage-sqlite/build.gradle.kts b/storage-sqlite/build.gradle.kts index 1867078..1a8ad5e 100644 --- a/storage-sqlite/build.gradle.kts +++ b/storage-sqlite/build.gradle.kts @@ -15,7 +15,9 @@ kotlin { sourceSets { commonMain.dependencies { - api(project(":storage-core")) + api(project(":message-store-api")) + api(project(":storage-bundle")) + api(project(":working-memory-api")) api(libs.sqldelight.runtime) api(libs.sqldelight.coroutines) } diff --git a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteConversationStore.kt b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteConversationStore.kt index 45862b4..842411a 100644 --- a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteConversationStore.kt +++ b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteConversationStore.kt @@ -1,8 +1,8 @@ package pw.binom.agentik.storage.sqlite import kotlin.time.Instant -import pw.binom.agentik.storage.ConversationRecord -import pw.binom.agentik.storage.ConversationStore +import pw.binom.agentik.messageStore.ConversationRecord +import pw.binom.agentik.messageStore.ConversationStore /** * SQLite-реализация [ConversationStore]. diff --git a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteEventStore.kt b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteEventStore.kt index 9484baa..631a851 100644 --- a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteEventStore.kt +++ b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteEventStore.kt @@ -2,9 +2,9 @@ package pw.binom.agentik.storage.sqlite import kotlin.time.Instant import mu.KotlinLogging -import pw.binom.agentik.storage.events.EventRecord -import pw.binom.agentik.storage.events.EventStore -import pw.binom.agentik.storage.events.EventType +import pw.binom.agentik.messageStore.events.EventRecord +import pw.binom.agentik.messageStore.events.EventStore +import pw.binom.agentik.messageStore.events.EventType import pw.binom.agentik.storage.sqlite.Agent_event as DbAgentEvent private val log = KotlinLogging.logger {} diff --git a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteMessageStore.kt b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteMessageStore.kt index a856c36..5a78e38 100644 --- a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteMessageStore.kt +++ b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteMessageStore.kt @@ -1,11 +1,11 @@ package pw.binom.agentik.storage.sqlite import kotlinx.serialization.json.Json -import pw.binom.agentik.storage.MessageRecord -import pw.binom.agentik.storage.MessageStore -import pw.binom.agentik.storage.TokenStats -import pw.binom.agentik.storage.decodeBodyPayload -import pw.binom.agentik.storage.encodeBodyPayload +import pw.binom.agentik.messageStore.MessageRecord +import pw.binom.agentik.messageStore.MessageStore +import pw.binom.agentik.messageStore.TokenStats +import pw.binom.agentik.messageStore.decodeBodyPayload +import pw.binom.agentik.messageStore.encodeBodyPayload import kotlin.time.Instant /** diff --git a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteReflectionStore.kt b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteReflectionStore.kt index 404b322..774dfd0 100644 --- a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteReflectionStore.kt +++ b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteReflectionStore.kt @@ -6,9 +6,9 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow import mu.KotlinLogging -import pw.binom.agentik.storage.Reflection -import pw.binom.agentik.storage.ReflectionEvent -import pw.binom.agentik.storage.ReflectionStore +import pw.binom.agentik.messageStore.Reflection +import pw.binom.agentik.messageStore.ReflectionEvent +import pw.binom.agentik.messageStore.ReflectionStore import pw.binom.agentik.storage.sqlite.AgentikDatabase import pw.binom.agentik.storage.sqlite.Reflection as DbReflection import pw.binom.agentik.storage.sqlite.ReflectionQueries diff --git a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteStores.kt b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteStores.kt index 9756309..a9cdc9e 100644 --- a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteStores.kt +++ b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteStores.kt @@ -3,13 +3,13 @@ package pw.binom.agentik.storage.sqlite import app.cash.sqldelight.db.QueryResult import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver -import pw.binom.agentik.storage.ConversationStore -import pw.binom.agentik.storage.MessageStore -import pw.binom.agentik.storage.ReflectionStore -import pw.binom.agentik.storage.StorageBundle -import pw.binom.agentik.storage.events.EventStore +import pw.binom.agentik.messageStore.ConversationStore +import pw.binom.agentik.messageStore.MessageStore +import pw.binom.agentik.messageStore.ReflectionStore +import pw.binom.agentik.storageBundle.StorageBundle +import pw.binom.agentik.messageStore.events.EventStore import pw.binom.agentik.storage.sqlite.SqliteReflectionStore -import pw.binom.agentik.storage.WorkingMemoryStore +import pw.binom.agentik.workingMemory.WorkingMemoryStore /** * Корневой объект SQLite-слоя: держит [SqlDriver] и пять store'ов (включая diff --git a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteWorkingMemoryStore.kt b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteWorkingMemoryStore.kt index e0ff927..a80df9f 100644 --- a/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteWorkingMemoryStore.kt +++ b/storage-sqlite/src/jvmMain/kotlin/pw/binom/agentik/storage/sqlite/SqliteWorkingMemoryStore.kt @@ -1,9 +1,9 @@ package pw.binom.agentik.storage.sqlite import kotlinx.serialization.json.Json -import pw.binom.agentik.storage.WorkingMemoryEntry -import pw.binom.agentik.storage.WorkingMemoryRow -import pw.binom.agentik.storage.WorkingMemoryStore +import pw.binom.agentik.workingMemory.WorkingMemoryEntry +import pw.binom.agentik.workingMemory.WorkingMemoryRow +import pw.binom.agentik.workingMemory.WorkingMemoryStore import kotlin.time.Instant /** @@ -90,4 +90,4 @@ private fun Working_memory.toRow(): WorkingMemoryRow { ) } -private fun newId(): String = pw.binom.agentik.storage.Ids.new("wm") +private fun newId(): String = pw.binom.agentik.messageStore.Ids.new("wm") diff --git a/storage-sqlite/src/jvmTest/kotlin/pw/binom/agentik/storage/sqlite/ReflectionStoreTest.kt b/storage-sqlite/src/jvmTest/kotlin/pw/binom/agentik/storage/sqlite/ReflectionStoreTest.kt index f628f70..9cce5e6 100644 --- a/storage-sqlite/src/jvmTest/kotlin/pw/binom/agentik/storage/sqlite/ReflectionStoreTest.kt +++ b/storage-sqlite/src/jvmTest/kotlin/pw/binom/agentik/storage/sqlite/ReflectionStoreTest.kt @@ -5,8 +5,8 @@ import kotlin.test.assertEquals import kotlin.test.assertNull import kotlin.test.assertNotNull import kotlin.time.Instant -import pw.binom.agentik.storage.Reflection -import pw.binom.agentik.storage.ReflectionEvent +import pw.binom.agentik.messageStore.Reflection +import pw.binom.agentik.messageStore.ReflectionEvent class ReflectionStoreTest { diff --git a/storage-sqlite/src/jvmTest/kotlin/pw/binom/agentik/storage/sqlite/SqliteEventStoreTest.kt b/storage-sqlite/src/jvmTest/kotlin/pw/binom/agentik/storage/sqlite/SqliteEventStoreTest.kt index 8a0a7d0..cec7b39 100644 --- a/storage-sqlite/src/jvmTest/kotlin/pw/binom/agentik/storage/sqlite/SqliteEventStoreTest.kt +++ b/storage-sqlite/src/jvmTest/kotlin/pw/binom/agentik/storage/sqlite/SqliteEventStoreTest.kt @@ -1,8 +1,8 @@ package pw.binom.agentik.storage.sqlite import kotlinx.coroutines.test.runTest -import pw.binom.agentik.storage.events.EventRecord -import pw.binom.agentik.storage.events.EventType +import pw.binom.agentik.messageStore.events.EventRecord +import pw.binom.agentik.messageStore.events.EventType import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test diff --git a/storage-core/build.gradle.kts b/working-memory-api/build.gradle.kts similarity index 54% rename from storage-core/build.gradle.kts rename to working-memory-api/build.gradle.kts index b788f82..6c4ce1d 100644 --- a/storage-core/build.gradle.kts +++ b/working-memory-api/build.gradle.kts @@ -3,24 +3,22 @@ plugins { alias(libs.plugins.kotlin.serialization) } +// Public API для mutable working-memory — runtime context агента (compaction, +// order_idx, summary entries). Зависит от :message-store-api для Ids (wm- префикс). +// +// НЕ нужен тонким клиентам — только серверному рантайму (`:standalone`, `:agentik-cli`, +// будущий `:android-agent` core). + kotlin { jvmToolchain(21) - // Зеркалит набор :proto / :server / :memory-api — KMP-модуль с интерфейсами - // хранилища и разговорной истории, без платформенного IO. Конкретные - // реализации (sqlite, in-memory, android) живут в отдельных модулях. jvm() - macosX64() - macosArm64() - iosX64() - iosArm64() - iosSimulatorArm64() linuxX64() - linuxArm64() mingwX64() sourceSets { commonMain.dependencies { + api(project(":message-store-api")) api(libs.kotlinx.coroutines.core) api(libs.kotlinx.serialization.core) api(libs.kotlinx.serialization.json) diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/WorkingMemoryEntry.kt b/working-memory-api/src/commonMain/kotlin/pw/binom/agentik/workingMemory/WorkingMemoryEntry.kt similarity index 96% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/WorkingMemoryEntry.kt rename to working-memory-api/src/commonMain/kotlin/pw/binom/agentik/workingMemory/WorkingMemoryEntry.kt index c229a31..88bff54 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/WorkingMemoryEntry.kt +++ b/working-memory-api/src/commonMain/kotlin/pw/binom/agentik/workingMemory/WorkingMemoryEntry.kt @@ -1,7 +1,9 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.workingMemory import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import pw.binom.agentik.messageStore.Content +import pw.binom.agentik.messageStore.MessageContext /** * Запись в working memory диалога: ровно то, что агент сейчас видит в diff --git a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/WorkingMemoryStore.kt b/working-memory-api/src/commonMain/kotlin/pw/binom/agentik/workingMemory/WorkingMemoryStore.kt similarity index 98% rename from storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/WorkingMemoryStore.kt rename to working-memory-api/src/commonMain/kotlin/pw/binom/agentik/workingMemory/WorkingMemoryStore.kt index a055df1..86f42e2 100644 --- a/storage-core/src/commonMain/kotlin/pw/binom/agentik/storage/WorkingMemoryStore.kt +++ b/working-memory-api/src/commonMain/kotlin/pw/binom/agentik/workingMemory/WorkingMemoryStore.kt @@ -1,4 +1,4 @@ -package pw.binom.agentik.storage +package pw.binom.agentik.workingMemory import kotlin.time.Instant