refactor(storage): split :storage-core into message-store-api + working-memory-api
ci / JVM build + tests (push) Failing after 2m5s
ci / JVM build + tests (push) Failing after 2m5s
Разделяет монолитный :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
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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<ConversationTurn> {
|
||||
internal suspend fun recentTurns(storage: pw.binom.agentik.storageBundle.StorageBundle, conversationId: String, maxTurns: Int): List<ConversationTurn> {
|
||||
val rows = storage.workingMemoryStore.list(conversationId)
|
||||
val pairs = mutableListOf<ConversationTurn>()
|
||||
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<pw.binom.agentik.storage.Content>.text(): String =
|
||||
filterIsInstance<pw.binom.agentik.storage.Content.Text>().joinToString("\n") { it.body }
|
||||
internal fun List<pw.binom.agentik.messageStore.Content>.text(): String =
|
||||
filterIsInstance<pw.binom.agentik.messageStore.Content.Text>().joinToString("\n") { it.body }
|
||||
|
||||
@@ -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<pw.binom.agentik.storage.Reflection> =
|
||||
val recentReflections: List<pw.binom.agentik.messageStore.Reflection> =
|
||||
if (config.reflection.topK > 0) kotlinx.coroutines.runBlocking {
|
||||
storage.reflectionStore.listRecent(config.reflection.topK)
|
||||
} else emptyList()
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
@@ -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<NamedTool> = 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,
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
@@ -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?,
|
||||
|
||||
+4
-4
@@ -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 {}
|
||||
|
||||
|
||||
+13
-13
@@ -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, Any?>): String {
|
||||
val el = JsonElement.serializer()
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
|
||||
@@ -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<NamedTool> = 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<pw.binom.agentik.storage.MessageRecord.UserMessage>(msgs[0])
|
||||
val err = assertIs<pw.binom.agentik.storage.MessageRecord.Error>(msgs[1])
|
||||
assertIs<pw.binom.agentik.messageStore.MessageRecord.UserMessage>(msgs[0])
|
||||
val err = assertIs<pw.binom.agentik.messageStore.MessageRecord.Error>(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<pw.binom.agentik.storage.MessageRecord.UserMessage>(msgs[0])
|
||||
assertIs<pw.binom.agentik.messageStore.MessageRecord.UserMessage>(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<pw.binom.agentik.storage.MessageRecord.ToolResult>().firstOrNull()
|
||||
val toolResult = msgs.filterIsInstance<pw.binom.agentik.messageStore.MessageRecord.ToolResult>().firstOrNull()
|
||||
assertNotNull(toolResult, "tool result должен быть в audit — tool выполнился нормально")
|
||||
val toolResultResult = toolResult!!.result!!
|
||||
assertTrue(toolResultResult.contains("echo"), "tool result содержит реальный ответ тулы: $toolResultResult")
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ class ChatAgentToolsetsTest {
|
||||
|
||||
private fun newAgent(
|
||||
toolsets: List<ToolsetContribution> = emptyList(),
|
||||
): Pair<ChatAgent, pw.binom.agentik.storage.StorageBundle> {
|
||||
): Pair<ChatAgent, pw.binom.agentik.storageBundle.StorageBundle> {
|
||||
val storage = SqliteStores.inMemory().asBundle()
|
||||
val agent = ChatAgent(
|
||||
id = "test-agent",
|
||||
|
||||
@@ -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")
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+7
-1
@@ -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
|
||||
+6
-1
@@ -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
|
||||
+11
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user