Add GET /conversations/{id}/count endpoint for total/filtered message counts, update JournalStore API, and implement client/server support with tests.
release / Publish KMP libraries → caffeine Nexus (release) Successful in 1m4s

This commit is contained in:
2026-09-23 05:43:55 +03:00
parent a81d92f489
commit d1b4f897b7
6 changed files with 51 additions and 5 deletions
+3
View File
@@ -49,6 +49,9 @@ kotlin {
implementation(kotlin("test"))
implementation(libs.ktor.server.test.host)
implementation(libs.ktor.server.cio)
implementation(libs.ktor.client.content.negotiation)
implementation(libs.ktor.serialization.kotlinx.json)
implementation(project(":journal-inmemory"))
}
}
}
@@ -23,6 +23,10 @@ import pw.binom.agentik.journal.JournalStore
* project'нутые proto-[pw.binom.agentik.proto.Message]), здесь клиент
* получает полный transcript с tool-call/tool-result/error payload-ами,
* turn-tokens и context-метаданными.
* - `GET /conversations/{id}/count?after=` — сколько сообщений в диалоге
* всего (без `after`) или строго позже `after` (с `after`). Лёгкий
* endpoint для UI-бейджей "N новых сообщений" и compaction-метрик;
* тело ответа — JSON `{"count": <Long>}`.
*
* **Read-only:** [JournalStore] не имеет `append` — запись только через
* writer-референс, который ChatAgent держит внутри (тип `MutableJournalStore`,
@@ -40,5 +44,19 @@ fun Route.journalRoutes(
val limit = call.request.queryParameters["limit"]?.toIntOrNull() ?: JournalStore.PAGE_SIZE
call.respond(journal.list(id, after, offset, limit))
}
get("/conversations/{id}/count") {
val id = call.parameters["id"]!!
val after = call.parseAfter()
val count = if (after == null) {
journal.count(id)
} else {
journal.count(id, after)
}
call.respond(CountResponse(count = count))
}
}
}
/** Тело ответа `GET /conversations/{id}/count`. */
@kotlinx.serialization.Serializable
private data class CountResponse(val count: Long)
@@ -44,6 +44,8 @@ class BearerTokenTest {
) : Agent {
override val journal: JournalStore = object : JournalStore {
override suspend fun list(conversationId: String, after: Instant, offset: Int, limit: Int) = emptyList<MessageRecord>()
override suspend fun count(conversationId: String): Long = 0L
override suspend fun count(conversationId: String, after: Instant): Long = 0L
override fun listFlow(conversationId: String, after: Instant, pageSize: Int) = emptyFlow<MessageRecord>()
override fun close() {}
}