fix: clarify Dismiss now informs the agent instead of silently dropping (#580)
* fix(#572): clarify Dismiss now informs agent instead of silently dropping * fix(#572): clarify Dismiss rejects the question (no answer) instead of telling agent to proceed --------- Co-authored-by: M57 <m57@hermes-control.app>
This commit is contained in:
1 parent
109fb1a04d
commit
e48778291a
2 files changed
+94
No files matched your search
@@ -105,6 +105,17 @@ data class ClarifyUi(
|
||||
val clarifyId: String? = null,
|
||||
)
|
||||
|
||||
/**
|
||||
* String sent to the agent when a clarify prompt is dismissed (the Dismiss
|
||||
* button). This is a *reject* — "I'm not answering this question" — NOT an
|
||||
* instruction to proceed. Deliberately NOT the CLI's interrupt sentinel
|
||||
* ("...Use your best judgement to proceed."): a mobile Dismiss is a
|
||||
* skip-the-question gesture, not an interrupt of the whole turn. The agent is
|
||||
* unblocked but told no answer was given, so it re-asks or backs off rather
|
||||
* than charging ahead.
|
||||
*/
|
||||
private const val CLARIFY_DISMISS_RESPONSE = "The user cancelled — no answer provided."
|
||||
|
||||
/** Transient — not persisted. Holds a pending sudo.password request. */
|
||||
data class SudoPromptUi(
|
||||
val requestId: String?,
|
||||
@@ -1225,8 +1236,47 @@ class ChatViewModel(
|
||||
_uiState.update { it.copy(showSessionPicker = !it.showSessionPicker) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismiss the active clarify prompt and reject it (tell the agent no answer
|
||||
* was given).
|
||||
*
|
||||
* The backend's clarify tool blocks the agent thread waiting for a response
|
||||
* (CLI timeout is 120s). A silent dismiss would leave the agent hanging
|
||||
* until that timeout, so we send a cancel sentinel
|
||||
* ([CLARIFY_DISMISS_RESPONSE]) over `clarify.respond` to unblock it.
|
||||
*
|
||||
* This is a *reject*, not an instruction to proceed — the agent is told no
|
||||
* answer was provided and should re-ask or back off, NOT charge ahead.
|
||||
*
|
||||
* Unlike [respondToClarify] we do NOT append a user chat bubble: a dismiss
|
||||
* is not something the user typed, so faking a USER message would be
|
||||
* dishonest. We instead surface a short SYSTEM note so the dismissal is
|
||||
* visible in the transcript.
|
||||
*/
|
||||
fun dismissClarify() {
|
||||
val sessionId = _uiState.value.currentSessionId ?: return
|
||||
val clarifyId = _uiState.value.clarifyRequest?.clarifyId
|
||||
_uiState.update { it.copy(clarifyRequest = null) }
|
||||
|
||||
addSystemMessage("Clarify dismissed — no answer sent", persist = true)
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val params =
|
||||
mutableMapOf<String, Any>(
|
||||
"session_id" to sessionId,
|
||||
"response" to CLARIFY_DISMISS_RESPONSE,
|
||||
"answer" to CLARIFY_DISMISS_RESPONSE,
|
||||
)
|
||||
if (clarifyId != null) {
|
||||
params["clarify_id"] = clarifyId
|
||||
params["request_id"] = clarifyId
|
||||
}
|
||||
wsClient.send(
|
||||
method = WsMethods.CLARIFY_RESPOND,
|
||||
params = params,
|
||||
onSent = { id -> trackRequest(id, WsMethods.CLARIFY_RESPOND) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun respondToClarify(option: String) {
|
||||
|
||||
Reference in new issue
Block a user