From d8e3992c33c1b548365dd7b50d6d9e734efb098f Mon Sep 17 00:00:00 2001 From: Hy4ri Date: Mon, 31 Aug 2026 11:10:26 +0300 Subject: [PATCH] fix: memory screen reset actions serialization error (fixes #1020) --- .../m57/hermescontrol/data/model/MemoryResponse.kt | 11 +++++++++++ .../m57/hermescontrol/data/remote/HermesApiService.kt | 4 ++-- .../m57/hermescontrol/ui/memory/MemoryViewModel.kt | 3 ++- .../hermescontrol/ui/memory/MemoryViewModelTest.kt | 11 ++++++----- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/m57/hermescontrol/data/model/MemoryResponse.kt b/app/src/main/java/com/m57/hermescontrol/data/model/MemoryResponse.kt index ef1e88f8..eb528cf5 100644 --- a/app/src/main/java/com/m57/hermescontrol/data/model/MemoryResponse.kt +++ b/app/src/main/java/com/m57/hermescontrol/data/model/MemoryResponse.kt @@ -13,3 +13,14 @@ data class BuiltinFileSizes( val memory: Long? = null, val user: Long? = null, ) + +@Serializable +data class MemoryResetRequest( + val target: String = "all", +) + +@Serializable +data class MemoryResetResponse( + val ok: Boolean = false, + val deleted: List = emptyList(), +) diff --git a/app/src/main/java/com/m57/hermescontrol/data/remote/HermesApiService.kt b/app/src/main/java/com/m57/hermescontrol/data/remote/HermesApiService.kt index 40e13100..7b92ec94 100644 --- a/app/src/main/java/com/m57/hermescontrol/data/remote/HermesApiService.kt +++ b/app/src/main/java/com/m57/hermescontrol/data/remote/HermesApiService.kt @@ -851,8 +851,8 @@ interface HermesApiService { @POST("api/memory/reset") suspend fun resetMemory( - @Body body: Map, - ): Response> + @Body body: MemoryResetRequest, + ): Response // ── Admin: Credential pool ──────────────────────────────────────── @GET("api/credentials/pool") diff --git a/app/src/main/java/com/m57/hermescontrol/ui/memory/MemoryViewModel.kt b/app/src/main/java/com/m57/hermescontrol/ui/memory/MemoryViewModel.kt index 85cb7657..926500f9 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/memory/MemoryViewModel.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/memory/MemoryViewModel.kt @@ -3,6 +3,7 @@ package com.m57.hermescontrol.ui.memory import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.m57.hermescontrol.data.model.LearningGraphResponse +import com.m57.hermescontrol.data.model.MemoryResetRequest import com.m57.hermescontrol.data.model.MemoryResponse import com.m57.hermescontrol.data.remote.ApiClient import com.m57.hermescontrol.data.remote.NetworkResult @@ -67,7 +68,7 @@ class MemoryViewModel : ViewModel(), ToastHost { if (_uiState.value.resetting != null) return _uiState.update { it.copy(resetting = target) } viewModelScope.launch { - val result = safeApiCall { ApiClient.hermesApi.resetMemory(mapOf("target" to target)) } + val result = safeApiCall { ApiClient.hermesApi.resetMemory(MemoryResetRequest(target = target)) } when (result) { is NetworkResult.Success -> _uiState.update { diff --git a/app/src/test/java/com/m57/hermescontrol/ui/memory/MemoryViewModelTest.kt b/app/src/test/java/com/m57/hermescontrol/ui/memory/MemoryViewModelTest.kt index b8de1cf5..1c5dd148 100644 --- a/app/src/test/java/com/m57/hermescontrol/ui/memory/MemoryViewModelTest.kt +++ b/app/src/test/java/com/m57/hermescontrol/ui/memory/MemoryViewModelTest.kt @@ -1,5 +1,7 @@ package com.m57.hermescontrol.ui.memory +import com.m57.hermescontrol.data.model.MemoryResetRequest +import com.m57.hermescontrol.data.model.MemoryResetResponse import com.m57.hermescontrol.data.model.MemoryProviderStatusRow import com.m57.hermescontrol.data.model.MemoryResponse import com.m57.hermescontrol.data.remote.ApiClient @@ -103,15 +105,15 @@ class MemoryViewModelTest { @Test fun `resetMemory posts target and reloads`() { - coEvery { mockApi.resetMemory(mapOf("target" to "all")) } returns - Response.success(emptyMap()) + coEvery { mockApi.resetMemory(MemoryResetRequest(target = "all")) } returns + Response.success(MemoryResetResponse(ok = true)) val vm = MemoryViewModel() vm.load() testDispatcher.scheduler.advanceUntilIdle() vm.resetMemory("all") testDispatcher.scheduler.advanceUntilIdle() - coVerify { mockApi.resetMemory(mapOf("target" to "all")) } + coVerify { mockApi.resetMemory(MemoryResetRequest(target = "all")) } assertEquals("Memory (all) reset successfully", vm.uiState.value.toastMessage) // One load + one reload after reset. coVerify(exactly = 2) { mockApi.getMemory() } @@ -119,7 +121,7 @@ class MemoryViewModelTest { @Test fun `resetMemory failure shows error toast`() { - coEvery { mockApi.resetMemory(mapOf("target" to "memory")) } returns + coEvery { mockApi.resetMemory(MemoryResetRequest(target = "memory")) } returns Response.error(500, "boom".toResponseBody()) val vm = MemoryViewModel() vm.resetMemory("memory") @@ -128,4 +130,3 @@ class MemoryViewModelTest { assertTrue(vm.uiState.value.toastMessage.orEmpty().contains("Failed to reset memory")) assertNull(vm.uiState.value.resetting) } -}