@@ -28,6 +28,7 @@ import kotlinx.coroutines.flow.SharingStarted
2828import kotlinx.coroutines.flow.StateFlow
2929import kotlinx.coroutines.flow.asStateFlow
3030import kotlinx.coroutines.flow.catch
31+import kotlinx.coroutines.CancellationException
3132import kotlinx.coroutines.flow.collectLatest
3233import kotlinx.coroutines.flow.debounce
3334import kotlinx.coroutines.flow.drop
@@ -266,25 +267,31 @@ class ChatViewModel(
266267 _error.value = null
267268 _failedDraft.value = null
268269 _selectedAgent.value = null
269− conn.events.events.collect { event ->
270− if (SessionRepository.isIdle(event, sessionId)) _running.value = false
271− if (SessionRepository.isError(event, sessionId)) {
272− _running.value = false
273− _error.value = container.string(R.string.error_agent_reported)
274− }
275− when (event) {
276− is PermissionUpdated ->
277− if (event.properties.sessionID == sessionId) _pendingPermission.value = event.properties
278− is PermissionReplied ->
279− if (event.properties.sessionID == sessionId && event.properties.permissionID == _pendingPermission.value?.id) _pendingPermission.value = null
280− is SessionUpdated ->
281− if (event.properties.info.id == sessionId) _sessionTitle.value = event.properties.info.displayTitle
282− is SessionDeleted ->
283− if (event.properties.info?.id == sessionId || event.properties.sessionID == sessionId) {
284− _sessionDeleted.value = true
285− }
286− else -> {}
270+ try {
271+ conn.events.events.collect { event ->
272+ if (SessionRepository.isIdle(event, sessionId)) _running.value = false
273+ if (SessionRepository.isError(event, sessionId)) {
274+ _running.value = false
275+ _error.value = container.string(R.string.error_agent_reported)
276+ }
277+ when (event) {
278+ is PermissionUpdated ->
279+ if (event.properties.sessionID == sessionId) _pendingPermission.value = event.properties
280+ is PermissionReplied ->
281+ if (event.properties.sessionID == sessionId && event.properties.permissionID == _pendingPermission.value?.id) _pendingPermission.value = null
282+ is SessionUpdated ->
283+ if (event.properties.info.id == sessionId) _sessionTitle.value = event.properties.info.displayTitle
284+ is SessionDeleted ->
285+ if (event.properties.info?.id == sessionId || event.properties.sessionID == sessionId) {
286+ _sessionDeleted.value = true
287+ }
288+ else -> {}
289+ }
287290 }
291+ } catch (e: CancellationException) {
292+ throw e
293+ } catch (e: Exception) {
294+ Log.w("ChatViewModel", "SSE event collector error", e)
288295 }
289296 }
290297 }
@@ -335,11 +342,17 @@ class ChatViewModel(
335342 viewModelScope.launch {
336343 container.activeConnection.collectLatest { conn ->
337344 if (conn == null) return@collectLatest
338− conn.events.state.collect { state ->
339− if ((state == EventStreamClient.ConnectionState.Disconnected ||
340− state == EventStreamClient.ConnectionState.Failed) && _running.value) {
341− _running.value = false
345+ try {
346+ conn.events.state.collect { state ->
347+ if ((state == EventStreamClient.ConnectionState.Disconnected ||
348+ state == EventStreamClient.ConnectionState.Failed) && _running.value) {
349+ _running.value = false
350+ }
342351 }
352+ } catch (e: CancellationException) {
353+ throw e
354+ } catch (e: Exception) {
355+ Log.w("ChatViewModel", "SSE state collector error", e)
343356 }
344357 }
345358 }