feat(enums): 接入 /meta/enums 权威枚举表,删掉客户端硬编码映射
客户端此前自带 platform / mood / mode 三张硬编码标签表,会与服务端漂移—— 实测已经漂了:客户端把 `web` 显示成「Web」,权威表里是「网页」。 - data:MetaApi(GET /api/v1/meta/enums)+ MetaDto + MetaRepository, 经 ApiClientFactory 创建以复用既有 token / 401 处理 - domain/enums/EnumCatalog.kt:标签查找器,**不含任何硬编码兜底表**; 不在表内的取值一律原样返回(api-client §1.1 的未知值回落红线); platformLabelOrNull 供 deviceId 前缀这类「认识/不认识要走不同回落」的调用方用; 空 id 或空 label 一律不入表(否则角标会显示空白,或查空串凭空借到别人的标签) - core/prefs/EnumPreferences.kt:last-good 快照,baseUrl+username 指纹闸门, 换服务器/账号即作废,登出清空 - EnumCatalogViewModel + LocalEnumCatalog:在 CyreneRoot 注入(与 LocalAppPrefs 同套路), 聊天角标与管理页共读同一份 - 删除 platformLabels / personaModeLabels / moodLabels;MessageSource 与 AdminFormat 改为查表,并保留各自原有的原样回落 为什么不留硬编码兜底表:没有登录就看不到任何消息,而权威表在登录前后即会拉取, 所以 last-good 快照几乎总是存在;留着硬编码表等于把「漂移」重新引进来,而且是无声的—— 旧标签和新鲜标签长得一模一样。 不转换的:trace kind/status、memory scope、thinking.mode、WS session_busy 的 mode 集合—— 它们都不在 /meta/enums 内,且原本就已按原样回落。 测试:115 全绿(88 → +27:MetaDtoRealPayload 8 / EnumCatalog 7 / EnumPrefs 3 / MessageSource 8,AdminFormatTest 改写并 +1),其中 /meta/enums 与登录响应一样 用真实抓取的响应体做夹具。
This commit is contained in:
1 parent
9f054aad28
commit
09a3222b7b
17 files changed
+693
-48
No files matched your search
@@ -0,0 +1,91 @@
|
||||
package top.yeij.cyrene.ui.chat
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Test
|
||||
import top.yeij.cyrene.data.api.dto.EnumItemDto
|
||||
import top.yeij.cyrene.data.api.dto.EnumTableDto
|
||||
import top.yeij.cyrene.data.api.dto.HistoryMessageDto
|
||||
import top.yeij.cyrene.domain.enums.EnumCatalog
|
||||
|
||||
/**
|
||||
* 来源角标的两种回落(S1.3):
|
||||
* 平台名查 `/meta/enums` 权威表(查不到原样显示),`deviceId` 的端粒度启发式与平台表无关。
|
||||
*/
|
||||
class MessageSourceTest {
|
||||
|
||||
private val catalog = EnumCatalog.of(
|
||||
EnumTableDto(
|
||||
platforms = listOf(
|
||||
EnumItemDto("web", "网页"),
|
||||
EnumItemDto("kook", "KOOK"),
|
||||
EnumItemDto("telegram", "Telegram"),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
private fun message(
|
||||
role: String = "user",
|
||||
platform: String? = null,
|
||||
deviceId: String? = null,
|
||||
) = HistoryMessageDto(
|
||||
id = "m1",
|
||||
sessionId = "web",
|
||||
role = role,
|
||||
platform = platform,
|
||||
deviceId = deviceId,
|
||||
createdAt = 1_791_088_571_785L,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `platform label comes from the authoritative table`() {
|
||||
// 权威表给 `web` 的标签是「网页」——旧硬编码表写的是 `Web`,此处即那处漂移的回归钉子。
|
||||
assertEquals("来自 网页", messageSourceLabel(message(platform = "web"), catalog))
|
||||
assertEquals("来自 KOOK", messageSourceLabel(message(platform = "kook"), catalog))
|
||||
assertEquals("发送至 Telegram", messageSourceLabel(message(role = "assistant", platform = "telegram"), catalog))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unknown platform is displayed verbatim`() {
|
||||
assertEquals("来自 mastodon", messageSourceLabel(message(platform = "mastodon"), catalog))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `without a table every platform is displayed verbatim rather than dropped`() {
|
||||
assertEquals("来自 web", messageSourceLabel(message(platform = "web"), EnumCatalog.Empty))
|
||||
assertEquals("来自 kook", messageSourceLabel(message(platform = "kook"), EnumCatalog.Empty))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `device heuristics stay independent of the platform table`() {
|
||||
assertEquals("来自 安卓", messageSourceLabel(message(deviceId = "voiceassist"), catalog))
|
||||
assertEquals("来自 Web(chrome)", messageSourceLabel(message(deviceId = "web:chrome:abc"), catalog))
|
||||
// deviceId 优先于 platform:两者都在时按 device 显示。
|
||||
assertEquals("来自 安卓", messageSourceLabel(message(platform = "web", deviceId = "voiceassist"), catalog))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `known platform prefix of an IM device id resolves to the table label`() {
|
||||
assertEquals("来自 KOOK", messageSourceLabel(message(deviceId = "kook:bot1:uid9"), catalog))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unknown platform prefix of an IM device id keeps the whole raw device id`() {
|
||||
assertEquals(
|
||||
"来自 matrix:acc1:uid9",
|
||||
messageSourceLabel(message(deviceId = "matrix:acc1:uid9"), catalog),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no source at all yields no badge`() {
|
||||
assertNull(messageSourceLabel(message(), catalog))
|
||||
assertNull(messageSourceLabel(message(platform = " "), catalog))
|
||||
assertNull(messageSourceLabel(message(deviceId = ""), catalog))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `blank device id falls through to the platform`() {
|
||||
assertEquals("来自 网页", messageSourceLabel(message(platform = "web", deviceId = " "), catalog))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user