feat(#125): fix clarify input pre-filling and parse/route clarify_id (#156)

* feat(#125): fix clarification input pre-filling and parse/route clarify_id

* fix(#156): fix ktlint violations in ChatViewModelTest.kt

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
M57andM57 authored and GitHub committed 2026-06-20 16:35:58 +03:00
1 parent 4544d88f8d
commit 03cfcf8504
5 files changed
+38 -7

No files matched your search

@@ -82,10 +82,11 @@ object EventParser {
"clarify.request" -> { "clarify.request" -> {
val text = payload?.get("text") as? String val text = payload?.get("text") as? String
val rawOptions = payload?.get("options") val rawOptions = payload?.get("options")
val clarifyId = payload?.get("clarify_id") as? String ?: payload?.get("request_id") as? String
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val options = (rawOptions as? List<*>)?.filterIsInstance<String>() val options = (rawOptions as? List<*>)?.filterIsInstance<String>()
WsEvent.ClarifyRequest(text, options) WsEvent.ClarifyRequest(text, options, clarifyId)
} }
"status.update" -> { "status.update" -> {
@@ -56,6 +56,7 @@ sealed class WsEvent {
data class ClarifyRequest( data class ClarifyRequest(
val text: String?, val text: String?,
val options: List<String>?, val options: List<String>?,
val clarifyId: String? = null,
) : WsEvent() ) : WsEvent()
// ── Status ─────────────────────────────────────────────────────────── // ── Status ───────────────────────────────────────────────────────────
@@ -824,7 +824,7 @@ private fun ClarifyDialog(
onOptionSelected: (String) -> Unit, onOptionSelected: (String) -> Unit,
onDismiss: () -> Unit, onDismiss: () -> Unit,
) { ) {
var typedText by rememberSaveable(clarify) { mutableStateOf(clarify.text) } var typedText by rememberSaveable(clarify.text) { mutableStateOf(clarify.text) }
AlertDialog( AlertDialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
@@ -70,6 +70,7 @@ data class SessionUi(
data class ClarifyUi( data class ClarifyUi(
val text: String, val text: String,
val options: List<String>, val options: List<String>,
val clarifyId: String? = null,
) )
class ChatViewModel( class ChatViewModel(
@@ -164,6 +165,7 @@ class ChatViewModel(
ClarifyUi( ClarifyUi(
text = event.text.orEmpty(), text = event.text.orEmpty(),
options = event.options.orEmpty(), options = event.options.orEmpty(),
clarifyId = event.clarifyId,
), ),
) )
} }
@@ -888,6 +890,7 @@ class ChatViewModel(
fun respondToClarify(option: String) { fun respondToClarify(option: String) {
val sessionId = _uiState.value.currentSessionId ?: return val sessionId = _uiState.value.currentSessionId ?: return
val clarifyId = _uiState.value.clarifyRequest?.clarifyId
_uiState.update { it.copy(clarifyRequest = null) } _uiState.update { it.copy(clarifyRequest = null) }
val userMessage = val userMessage =
@@ -908,9 +911,19 @@ class ChatViewModel(
} }
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val params =
mutableMapOf<String, Any>(
"session_id" to sessionId,
"response" to option,
"answer" to option,
)
if (clarifyId != null) {
params["clarify_id"] = clarifyId
params["request_id"] = clarifyId
}
wsClient.send( wsClient.send(
method = WsMethods.CLARIFY_RESPOND, method = WsMethods.CLARIFY_RESPOND,
params = mapOf("session_id" to sessionId, "response" to option), params = params,
onSent = { id -> trackRequest(id, WsMethods.CLARIFY_RESPOND) }, onSent = { id -> trackRequest(id, WsMethods.CLARIFY_RESPOND) },
) )
} }
@@ -297,12 +297,13 @@ class ChatViewModelTest {
mockEventsFlow.emit(WsEvent.RpcResult(createReqId, mapOf("session_id" to "session-123"))) mockEventsFlow.emit(WsEvent.RpcResult(createReqId, mapOf("session_id" to "session-123")))
advanceUntilIdle() advanceUntilIdle()
mockEventsFlow.emit(WsEvent.ClarifyRequest("Please choose:", listOf("Yes", "No"))) mockEventsFlow.emit(WsEvent.ClarifyRequest("Please choose:", listOf("Yes", "No"), "clarify-123"))
advanceUntilIdle() advanceUntilIdle()
var state = viewModel.uiState.value var state = viewModel.uiState.value
assertEquals("Please choose:", state.clarifyRequest?.text) assertEquals("Please choose:", state.clarifyRequest?.text)
assertEquals(listOf("Yes", "No"), state.clarifyRequest?.options) assertEquals(listOf("Yes", "No"), state.clarifyRequest?.options)
assertEquals("clarify-123", state.clarifyRequest?.clarifyId)
// Respond to clarify // Respond to clarify
viewModel.respondToClarify("Yes") viewModel.respondToClarify("Yes")
@@ -320,7 +321,14 @@ class ChatViewModelTest {
verify { verify {
HermesWsClient.send( HermesWsClient.send(
method = WsMethods.CLARIFY_RESPOND, method = WsMethods.CLARIFY_RESPOND,
params = mapOf("session_id" to "session-123", "response" to "Yes"), params =
mapOf(
"session_id" to "session-123",
"response" to "Yes",
"answer" to "Yes",
"clarify_id" to "clarify-123",
"request_id" to "clarify-123",
),
onSent = any(), onSent = any(),
) )
} }
@@ -347,12 +355,13 @@ class ChatViewModelTest {
mockEventsFlow.emit(WsEvent.RpcResult(createReqId, mapOf("session_id" to "session-123"))) mockEventsFlow.emit(WsEvent.RpcResult(createReqId, mapOf("session_id" to "session-123")))
advanceUntilIdle() advanceUntilIdle()
mockEventsFlow.emit(WsEvent.ClarifyRequest("Please explain:", emptyList())) mockEventsFlow.emit(WsEvent.ClarifyRequest("Please explain:", emptyList(), "clarify-456"))
advanceUntilIdle() advanceUntilIdle()
var state = viewModel.uiState.value var state = viewModel.uiState.value
assertEquals("Please explain:", state.clarifyRequest?.text) assertEquals("Please explain:", state.clarifyRequest?.text)
assertTrue(state.clarifyRequest?.options.isNullOrEmpty()) assertTrue(state.clarifyRequest?.options.isNullOrEmpty())
assertEquals("clarify-456", state.clarifyRequest?.clarifyId)
// Respond to clarify with custom text // Respond to clarify with custom text
viewModel.respondToClarify("This is my custom response text") viewModel.respondToClarify("This is my custom response text")
@@ -369,7 +378,14 @@ class ChatViewModelTest {
verify { verify {
HermesWsClient.send( HermesWsClient.send(
method = WsMethods.CLARIFY_RESPOND, method = WsMethods.CLARIFY_RESPOND,
params = mapOf("session_id" to "session-123", "response" to "This is my custom response text"), params =
mapOf(
"session_id" to "session-123",
"response" to "This is my custom response text",
"answer" to "This is my custom response text",
"clarify_id" to "clarify-456",
"request_id" to "clarify-456",
),
onSent = any(), onSent = any(),
) )
} }