@@ -311,7 +311,6 @@ class ChatController(
|
311 | 311 | } |
312 | 312 | } |
313 | 313 | |
314 | | -/** Applies gateway chat/agent stream events to local transcript and pending-run state. */ |
315 | 314 | fun handleGatewayEvent( |
316 | 315 | event: String, |
317 | 316 | payloadJson: String?, |
@@ -321,7 +320,6 @@ class ChatController(
|
321 | 320 | scope.launch { pollHealthIfNeeded(force = false) } |
322 | 321 | } |
323 | 322 | "health" -> { |
324 | | -// If we receive a health snapshot, the gateway is reachable. |
325 | 323 | _healthOk.value = true |
326 | 324 | } |
327 | 325 | "seqGap" -> { |
@@ -334,7 +332,7 @@ class ChatController(
|
334 | 332 | } |
335 | 333 | "sessions.changed" -> { |
336 | 334 | if (payloadJson.isNullOrBlank()) { |
337 | | -scope.launch { fetchSessions(limit = _sessions.value.size.takeIf { it > 0 } ?: 100) } |
| 335 | +refreshSessionsForCurrentWindow() |
338 | 336 | } else { |
339 | 337 | handleSessionsChangedEvent(payloadJson) |
340 | 338 | } |
@@ -400,6 +398,10 @@ class ChatController(
|
400 | 398 | } |
401 | 399 | } |
402 | 400 | |
| 401 | +private fun refreshSessionsForCurrentWindow() { |
| 402 | + scope.launch { fetchSessions(limit = _sessions.value.size.takeIf { it > 0 } ?: 100) } |
| 403 | + } |
| 404 | + |
403 | 405 | private suspend fun pollHealthIfNeeded(force: Boolean) { |
404 | 406 | val now = System.currentTimeMillis() |
405 | 407 | val last = lastHealthPollAtMs |
@@ -491,22 +493,25 @@ class ChatController(
|
491 | 493 | removeSessionEntry(payload["sessionKey"].asStringOrNull() ?: payload["key"].asStringOrNull()) |
492 | 494 | return |
493 | 495 | } |
494 | | -val entry = payload["session"].asObjectOrNull()?.let(::parseSessionEntry) ?: parseSessionEntry(payload) |
| 496 | +val entry = parseEventSessionEntry(payload) |
495 | 497 | if (entry != null) { |
496 | 498 | upsertSessionEntry(entry) |
497 | 499 | } else { |
498 | | -scope.launch { fetchSessions(limit = _sessions.value.size.takeIf { it > 0 } ?: 100) } |
| 500 | +refreshSessionsForCurrentWindow() |
499 | 501 | } |
500 | 502 | } |
501 | 503 | |
502 | 504 | private fun handleSessionMessageEvent(payloadJson: String) { |
503 | 505 | val payload = json.parseToJsonElement(payloadJson).asObjectOrNull() ?: return |
504 | | -val entry = payload["session"].asObjectOrNull()?.let(::parseSessionEntry) ?: parseSessionEntry(payload) |
| 506 | +val entry = parseEventSessionEntry(payload) |
505 | 507 | if (entry != null) { |
506 | 508 | upsertSessionEntry(entry) |
507 | 509 | } |
508 | 510 | } |
509 | 511 | |
| 512 | +private fun parseEventSessionEntry(payload: JsonObject): ChatSessionEntry? = |
| 513 | + payload["session"].asObjectOrNull()?.let(::parseSessionEntry) ?: parseSessionEntry(payload) |
| 514 | + |
510 | 515 | private fun handleAgentEvent(payloadJson: String) { |
511 | 516 | val payload = json.parseToJsonElement(payloadJson).asObjectOrNull() ?: return |
512 | 517 | val sessionKey = payload["sessionKey"].asStringOrNull()?.trim() |
|