diff --git a/webclient/src/composables/useWebSocket.js b/webclient/src/composables/useWebSocket.js index 93fad56..e7550d4 100644 --- a/webclient/src/composables/useWebSocket.js +++ b/webclient/src/composables/useWebSocket.js @@ -26,6 +26,7 @@ let retryCount = 0 let retryTimer = null let destroyed = false + let _isReconnect = false // true when this open is a retry, not the first connect function connect(id) { sessionId = id @@ -61,6 +62,7 @@ connected.value = true reconnecting.value = false reconnectFailed.value = false + _isReconnect = retryCount > 0 retryCount = 0 } @@ -116,6 +118,15 @@ case 'profile_switched': chat.onProfileSwitched(event); break case 'context_compressed':chat.onContextCompressed(event); break case 'error': chat.onError(event); break + case 'heartbeat': break // keep-alive ping, no action needed + case 'session_sync': + // On reconnect: reload session history so the client sees the saved response + // even if the agent finished while the client was disconnected. + if (_isReconnect && sessionId) { + _isReconnect = false + chat.reloadSession(sessionId) + } + break } } diff --git a/webclient/src/stores/chat.js b/webclient/src/stores/chat.js index 4e2e141..3d260d7 100644 --- a/webclient/src/stores/chat.js +++ b/webclient/src/stores/chat.js @@ -57,6 +57,22 @@ } } + // Force-reload session history from the server, bypassing the same-id guard. + // Called after WebSocket reconnect so the client sees the saved response + // even if streaming finished while the client was disconnected. + async function reloadSession(id) { + if (!id) return + try { + const session = await api.getSession(id) + currentProfileId.value = session.profile_id ?? null + messages.value = buildMessageList(session.messages ?? []) + if (session.context_token_count) contextTokens.value = session.context_token_count + if (session.max_context_tokens) maxContextTokens.value = session.max_context_tokens + } catch { + // Silently ignore — stale data is better than a crash + } + } + // Draft restore callback — set by InputBar let _draftRestoreCallback = null function onDraftRestore(cb) { _draftRestoreCallback = cb } @@ -392,6 +408,7 @@ loading, streamingMsg, loadSession, + reloadSession, saveDraft, onDraftRestore, appendUserMessage,