feat(chat): full sudo.request support with expire, cancel-unblock, secret fields (#1056)
This commit is contained in:
10 files changed
+348
-7
No files matched your search
@@ -855,4 +855,71 @@ class EventParserTest {
|
||||
assertEquals("1", todoUpdated.todos[1].parent)
|
||||
assertTrue(todoUpdated.todos[1].isSubtask)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testParseSudoRequest_returnsSudoRequest() {
|
||||
val params =
|
||||
mapOf(
|
||||
"type" to "sudo.request",
|
||||
"session_id" to "sess-sudo-1",
|
||||
"payload" to mapOf("request_id" to "sudo-1"),
|
||||
)
|
||||
val event = EventParser.parseParams(params)
|
||||
assertTrue(event is WsEvent.SudoRequest)
|
||||
val sudo = event as WsEvent.SudoRequest
|
||||
assertEquals("sudo-1", sudo.requestId)
|
||||
assertEquals("sess-sudo-1", sudo.sessionId)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testParseSudoExpire_returnsSudoExpire() {
|
||||
val params =
|
||||
mapOf(
|
||||
"type" to "sudo.expire",
|
||||
"session_id" to "sess-sudo-1",
|
||||
"payload" to mapOf("request_id" to "sudo-1"),
|
||||
)
|
||||
val event = EventParser.parseParams(params)
|
||||
assertTrue(event is WsEvent.SudoExpire)
|
||||
val expire = event as WsEvent.SudoExpire
|
||||
assertEquals("sudo-1", expire.requestId)
|
||||
assertEquals("sess-sudo-1", expire.sessionId)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testParseSecretRequest_withEnvVarAndPrompt() {
|
||||
val params =
|
||||
mapOf(
|
||||
"type" to "secret.request",
|
||||
"session_id" to "sess-secret-1",
|
||||
"payload" to
|
||||
mapOf(
|
||||
"request_id" to "secret-1",
|
||||
"env_var" to "GITHUB_TOKEN",
|
||||
"prompt" to "Enter your GitHub token to continue",
|
||||
),
|
||||
)
|
||||
val event = EventParser.parseParams(params)
|
||||
assertTrue(event is WsEvent.SecretRequest)
|
||||
val secret = event as WsEvent.SecretRequest
|
||||
assertEquals("secret-1", secret.requestId)
|
||||
assertEquals("sess-secret-1", secret.sessionId)
|
||||
assertEquals("GITHUB_TOKEN", secret.envVar)
|
||||
assertEquals("Enter your GitHub token to continue", secret.prompt)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testParseSecretExpire_returnsSecretExpire() {
|
||||
val params =
|
||||
mapOf(
|
||||
"type" to "secret.expire",
|
||||
"session_id" to "sess-secret-1",
|
||||
"payload" to mapOf("request_id" to "secret-1"),
|
||||
)
|
||||
val event = EventParser.parseParams(params)
|
||||
assertTrue(event is WsEvent.SecretExpire)
|
||||
val expire = event as WsEvent.SecretExpire
|
||||
assertEquals("secret-1", expire.requestId)
|
||||
assertEquals("sess-secret-1", expire.sessionId)
|
||||
}
|
||||
}
|
||||
@@ -3159,6 +3159,130 @@ class ChatViewModelTest {
|
||||
assertNull(viewModel.uiState.value.secretPrompt)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSudoExpire_clearsMatchingPrompt() =
|
||||
runTest {
|
||||
val (viewModel, _) = createViewModelWithSession()
|
||||
advanceUntilIdle()
|
||||
|
||||
mockEventsFlow.emit(WsEvent.SudoRequest(requestId = "sudo-1", sessionId = null))
|
||||
advanceUntilIdle()
|
||||
assertNotNull(viewModel.uiState.value.sudoPrompt)
|
||||
|
||||
mockEventsFlow.emit(WsEvent.SudoExpire(requestId = "sudo-1", sessionId = null))
|
||||
advanceUntilIdle()
|
||||
|
||||
assertNull(viewModel.uiState.value.sudoPrompt)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSudoExpire_ignoresNonMatchingRequestId() =
|
||||
runTest {
|
||||
val (viewModel, _) = createViewModelWithSession()
|
||||
advanceUntilIdle()
|
||||
|
||||
mockEventsFlow.emit(WsEvent.SudoRequest(requestId = "sudo-2", sessionId = null))
|
||||
advanceUntilIdle()
|
||||
assertNotNull(viewModel.uiState.value.sudoPrompt)
|
||||
|
||||
mockEventsFlow.emit(WsEvent.SudoExpire(requestId = "sudo-stale", sessionId = null))
|
||||
advanceUntilIdle()
|
||||
|
||||
assertNotNull(viewModel.uiState.value.sudoPrompt)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSecretExpire_clearsMatchingPrompt() =
|
||||
runTest {
|
||||
val (viewModel, _) = createViewModelWithSession()
|
||||
advanceUntilIdle()
|
||||
|
||||
mockEventsFlow.emit(WsEvent.SecretRequest(requestId = "secret-1", sessionId = null))
|
||||
advanceUntilIdle()
|
||||
assertNotNull(viewModel.uiState.value.secretPrompt)
|
||||
|
||||
mockEventsFlow.emit(WsEvent.SecretExpire(requestId = "secret-1", sessionId = null))
|
||||
advanceUntilIdle()
|
||||
|
||||
assertNull(viewModel.uiState.value.secretPrompt)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSecretRequest_setsEnvVarAndPrompt() =
|
||||
runTest {
|
||||
val (viewModel, _) = createViewModelWithSession()
|
||||
advanceUntilIdle()
|
||||
|
||||
mockEventsFlow.emit(
|
||||
WsEvent.SecretRequest(
|
||||
requestId = "secret-1",
|
||||
sessionId = null,
|
||||
envVar = "GITHUB_TOKEN",
|
||||
prompt = "Enter your GitHub token",
|
||||
),
|
||||
)
|
||||
advanceUntilIdle()
|
||||
|
||||
val prompt = viewModel.uiState.value.secretPrompt
|
||||
assertNotNull(prompt)
|
||||
assertEquals("GITHUB_TOKEN", prompt?.envVar)
|
||||
assertEquals("Enter your GitHub token", prompt?.prompt)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDismissSudo_sendsEmptyPassword() =
|
||||
runTest {
|
||||
val (viewModel, sessionId) = createViewModelWithSession()
|
||||
advanceUntilIdle()
|
||||
|
||||
mockEventsFlow.emit(WsEvent.SudoRequest(requestId = "sudo-1", sessionId = null))
|
||||
advanceUntilIdle()
|
||||
assertNotNull(viewModel.uiState.value.sudoPrompt)
|
||||
|
||||
viewModel.dismissSudo()
|
||||
advanceUntilIdle()
|
||||
|
||||
assertNull(viewModel.uiState.value.sudoPrompt)
|
||||
verify {
|
||||
HermesWsClient.send(
|
||||
WsMethods.SUDO_RESPOND,
|
||||
withArg { params ->
|
||||
assertEquals(sessionId, params["session_id"])
|
||||
assertEquals("", params["password"])
|
||||
assertEquals("sudo-1", params["request_id"])
|
||||
},
|
||||
any(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDismissSecret_sendsEmptyValue() =
|
||||
runTest {
|
||||
val (viewModel, sessionId) = createViewModelWithSession()
|
||||
advanceUntilIdle()
|
||||
|
||||
mockEventsFlow.emit(WsEvent.SecretRequest(requestId = "secret-1", sessionId = null))
|
||||
advanceUntilIdle()
|
||||
assertNotNull(viewModel.uiState.value.secretPrompt)
|
||||
|
||||
viewModel.dismissSecret()
|
||||
advanceUntilIdle()
|
||||
|
||||
assertNull(viewModel.uiState.value.secretPrompt)
|
||||
verify {
|
||||
HermesWsClient.send(
|
||||
WsMethods.SECRET_RESPOND,
|
||||
withArg { params ->
|
||||
assertEquals(sessionId, params["session_id"])
|
||||
assertEquals("", params["value"])
|
||||
assertEquals("secret-1", params["request_id"])
|
||||
},
|
||||
any(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ── Settings ─────────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
|
||||
Reference in new issue
Block a user