fix(chat): keep historical cache out of the live transcript tail (#1253)
This commit is contained in:
1 parent
c581fd23d1
commit
94ec95a33c
18 files changed
+805
-18
No files matched your search
+81
-1
@@ -41,7 +41,7 @@ class ChatMessagePagingDeviceTest {
|
||||
Room
|
||||
.databaseBuilder(context, HermesDatabase::class.java, databaseName)
|
||||
.setDriver(driver())
|
||||
.addMigrations(HermesDatabase.MIGRATION_8_9)
|
||||
.addMigrations(HermesDatabase.MIGRATION_8_9, HermesDatabase.MIGRATION_9_10)
|
||||
.build()
|
||||
repository = ChatPersistenceRepository(database.chatMessageDao())
|
||||
}
|
||||
@@ -234,6 +234,29 @@ class ChatMessagePagingDeviceTest {
|
||||
assertPagingIndexUsed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migration9to10PreservesAmbiguousUnsentUuidUserAsUnknown() =
|
||||
runBlocking {
|
||||
val unsent =
|
||||
ChatMessageEntity(
|
||||
id = "pending-before-upgrade",
|
||||
sessionId = "session",
|
||||
role = "USER",
|
||||
content = "may not have reached the server",
|
||||
timestamp = 1L,
|
||||
sortOrder = 1L,
|
||||
)
|
||||
createVersion9(listOf(unsent))
|
||||
openDatabase()
|
||||
val restored = database.chatMessageDao().getMessage(unsent.id)!!
|
||||
assertEquals("UNKNOWN", restored.messageProvenance)
|
||||
assertEquals(
|
||||
com.m57.hermescontrol.ui.chat.MessageProvenance.UNKNOWN,
|
||||
restored.toUiModel().messageProvenance,
|
||||
)
|
||||
assertEquals(unsent.content, restored.content)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun confirmedAliasPreservesLivePayloadAndCanonicalOrderAcrossReopen() =
|
||||
runBlocking {
|
||||
@@ -350,6 +373,63 @@ class ChatMessagePagingDeviceTest {
|
||||
}
|
||||
}
|
||||
|
||||
/** Build the exported v9 schema so Room validates the real non-destructive v9 -> v10 path. */
|
||||
private fun createVersion9(rows: List<ChatMessageEntity>) {
|
||||
database.close()
|
||||
context.deleteDatabase(databaseName)
|
||||
val schema =
|
||||
InstrumentationRegistry
|
||||
.getInstrumentation()
|
||||
.context.assets
|
||||
.open("com.m57.hermescontrol.data.local.HermesDatabase/9.json")
|
||||
.bufferedReader()
|
||||
.use { JSONObject(it.readText()).getJSONObject("database") }
|
||||
val file = context.getDatabasePath(databaseName)
|
||||
file.parentFile?.mkdirs()
|
||||
driver().open(file.absolutePath).use { connection ->
|
||||
val entity = schema.getJSONArray("entities").getJSONObject(0)
|
||||
connection.execSQL(entity.getString("createSql").replace("\${TABLE_NAME}", "chat_messages"))
|
||||
val indices = entity.getJSONArray("indices")
|
||||
for (index in 0 until indices.length()) {
|
||||
connection.execSQL(
|
||||
indices.getJSONObject(index).getString("createSql").replace("\${TABLE_NAME}", "chat_messages"),
|
||||
)
|
||||
}
|
||||
val setup = schema.getJSONArray("setupQueries")
|
||||
for (index in 0 until setup.length()) connection.execSQL(setup.getString(index))
|
||||
connection
|
||||
.prepare(
|
||||
"INSERT INTO chat_messages (id, session_id, role, content, reasoning_text, timestamp, " +
|
||||
"tool_name, tool_call_id, tool_status, is_streaming, display_kind, token_count, tps, " +
|
||||
"completion_id, rest_id, sort_group, sort_order) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
).use { insert ->
|
||||
rows.forEach { row ->
|
||||
insert.bindText(1, row.id)
|
||||
insert.bindText(2, row.sessionId)
|
||||
insert.bindText(3, row.role)
|
||||
insert.bindText(4, row.content)
|
||||
insert.bindText(5, row.reasoningText)
|
||||
insert.bindLong(6, row.timestamp)
|
||||
row.toolName?.let { insert.bindText(7, it) } ?: insert.bindNull(7)
|
||||
insert.bindText(8, row.toolCallId)
|
||||
row.toolStatus?.let { insert.bindText(9, it) } ?: insert.bindNull(9)
|
||||
insert.bindLong(10, if (row.isStreaming) 1L else 0L)
|
||||
row.displayKind?.let { insert.bindText(11, it) } ?: insert.bindNull(11)
|
||||
row.tokenCount?.let { insert.bindLong(12, it.toLong()) } ?: insert.bindNull(12)
|
||||
row.tps?.let { insert.bindDouble(13, it) } ?: insert.bindNull(13)
|
||||
row.completionId?.let { insert.bindText(14, it) } ?: insert.bindNull(14)
|
||||
row.restId?.let { insert.bindText(15, it) } ?: insert.bindNull(15)
|
||||
insert.bindLong(16, row.sortGroup.toLong())
|
||||
insert.bindLong(17, row.sortOrder)
|
||||
insert.step()
|
||||
insert.reset()
|
||||
insert.clearBindings()
|
||||
}
|
||||
}
|
||||
connection.execSQL("PRAGMA user_version = 9")
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertPagingIndexUsed() {
|
||||
database.close()
|
||||
driver().open(context.getDatabasePath(databaseName).absolutePath).use { connection ->
|
||||
|
||||
Reference in new issue
Block a user