Mobile was silently dropping two event types the gateway emits. This adds parsing + UI surfacing for both, bringing mobile to parity with desktop (which shows gateway errors as red toasts). - `error` (backend crash) -> WsEvent.GatewayError, surfaced in the existing error banner (mirrors how RpcError is handled). - `background.complete` (scheduled job finished) -> WsEvent.BackgroundComplete, surfaced as a non-blocking snackbar in ChatScreen. Changes: - WsEvent.kt: add GatewayError(message?) + BackgroundComplete(data?) sealed subtypes. - EventParser.kt: handle "error" + "background.complete"; unknowns still fall through to Unknown (no behavior change for existing event types). - ChatWsEventReducer.kt: onGatewayError (sets errorMessage, clears loading) + onBackgroundComplete (sets backgroundCompleteMessage); mirrors onRpcError. - ChatViewModel.kt: backgroundCompleteMessage state field, clearBackgroundComplete(), handleWsEvent branches (ViewModel owns the snackbar trigger). - ChatScreen.kt: pass backgroundCompleteMessage to ChatLifecycleEffects + a LaunchedEffect that shows the snackbar and calls clearBackgroundComplete(). - EventParserTest.kt: cover both new events (incl. missing-message case). Pure additive; sealed class + exhaustive when() preserved. Verified: compileDebugKotlin + ktlintCheck green; EventParserTest passes. Closes #527 Co-authored-by: M57 <m57@hermes-control.app>
This commit is contained in:
1 parent
480d29e481
commit
cf893585b1
6 files changed
+160
No files matched your search
@@ -111,6 +111,17 @@ object EventParser {
|
||||
WsEvent.StatusUpdate(status, payload)
|
||||
}
|
||||
|
||||
"error" -> {
|
||||
val message =
|
||||
payload?.get("message") as? String
|
||||
?: payload?.get("error") as? String
|
||||
WsEvent.GatewayError(message)
|
||||
}
|
||||
|
||||
"background.complete" -> {
|
||||
WsEvent.BackgroundComplete(payload)
|
||||
}
|
||||
|
||||
"session.updated" -> {
|
||||
WsEvent.SessionUpdated(payload)
|
||||
}
|
||||
|
||||
@@ -125,6 +125,33 @@ sealed class WsEvent {
|
||||
val sessionId: String?,
|
||||
) : WsEvent()
|
||||
|
||||
// ── Gateway-level errors ───────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Backend/unhandled failure surfaced by the gateway.
|
||||
*
|
||||
* Desktop shows these as red toasts (the gateway also writes
|
||||
* `[gateway.error]` lines to the console). Mobile was previously
|
||||
* dropping this event, so a crashing turn just silently stopped with no
|
||||
* explanation. Issue #527 surfaces it in the existing error banner.
|
||||
*/
|
||||
data class GatewayError(
|
||||
val message: String?,
|
||||
) : WsEvent()
|
||||
|
||||
// ── Background job completion ──────────────────────────────────────
|
||||
|
||||
/**
|
||||
* A scheduled/background job finished on the gateway.
|
||||
*
|
||||
* Desktop shows a "Background job finished" toast. Mobile surfaces this as
|
||||
* a non-blocking snackbar. The payload may carry `label`/`name` describing
|
||||
* the job. Issue #527.
|
||||
*/
|
||||
data class BackgroundComplete(
|
||||
val data: Map<String, Any?>?,
|
||||
) : WsEvent()
|
||||
|
||||
// ── Fallback ─────────────────────────────────────────────────────────
|
||||
|
||||
data class Unknown(
|
||||
|
||||
Reference in new issue
Block a user