fix mobile chat run reconnect (#993)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { startRunViaSocket, resumeSession, registerSessionHandlers, unregisterSessionHandlers, getChatRunSocket, respondToolApproval, onPeerUserMessage, respondClarify, type RunEvent, type ContentBlock as ContentBlockImport } from '@/api/hermes/chat'
|
||||
import { startRunViaSocket, resumeSession, registerSessionHandlers, unregisterSessionHandlers, getChatRunSocket, respondToolApproval, onPeerUserMessage, respondClarify, type RunEvent, type ResumeSessionPayload, type ContentBlock as ContentBlockImport } from '@/api/hermes/chat'
|
||||
import { deleteSession as deleteSessionApi, fetchSession, fetchSessions, setSessionModel, type HermesMessage, type SessionSummary } from '@/api/hermes/sessions'
|
||||
import { getActiveProfileName } from '@/api/client'
|
||||
import { getDownloadUrl } from '@/api/hermes/download'
|
||||
@@ -1277,6 +1277,107 @@ export const useChatStore = defineStore('chat', () => {
|
||||
activeAssistantMessageId = null
|
||||
}
|
||||
|
||||
const applyReconnectResume = (data: ResumeSessionPayload) => {
|
||||
if (data.session_id !== sid) return
|
||||
const target = sessions.value.find(s => s.id === sid)
|
||||
if (!target) return
|
||||
|
||||
if (data.isWorking) serverWorking.value.add(sid)
|
||||
else serverWorking.value.delete(sid)
|
||||
|
||||
if (data.queueLength && data.queueLength > 0) {
|
||||
queueLengths.value.set(sid, data.queueLength)
|
||||
} else {
|
||||
queueLengths.value.delete(sid)
|
||||
}
|
||||
|
||||
if (Array.isArray(data.queueMessages)) {
|
||||
replaceQueuedUserMessages(sid, normalizeQueuedUserMessages(data.queueMessages))
|
||||
} else if (!data.queueLength) {
|
||||
replaceQueuedUserMessages(sid, [])
|
||||
}
|
||||
|
||||
if (data.isAborting) {
|
||||
setAbortState({ aborting: true, synced: null })
|
||||
} else if (!data.isWorking) {
|
||||
setAbortState(null)
|
||||
}
|
||||
|
||||
if (data.inputTokens != null) target.inputTokens = data.inputTokens
|
||||
if (data.outputTokens != null) target.outputTokens = data.outputTokens
|
||||
if (data.contextTokens != null) target.contextTokens = data.contextTokens
|
||||
|
||||
if (Array.isArray(data.messages)) {
|
||||
target.messages = mapHermesMessages(data.messages as any[])
|
||||
const lastAssistant = [...target.messages].reverse().find(m => m.role === 'assistant')
|
||||
if (data.isWorking && lastAssistant) {
|
||||
lastAssistant.isStreaming = true
|
||||
activeAssistantMessageId = lastAssistant.id
|
||||
if (lastAssistant.reasoning) noteReasoningStart(lastAssistant.id)
|
||||
} else {
|
||||
activeAssistantMessageId = null
|
||||
}
|
||||
}
|
||||
|
||||
if (data.events?.length) {
|
||||
for (const evt of data.events) {
|
||||
const e = evt.data as RunEvent
|
||||
switch (e.event) {
|
||||
case 'compression.started':
|
||||
setCompressionState({
|
||||
compressing: true,
|
||||
messageCount: (e as any).message_count || 0,
|
||||
beforeTokens: (e as any).token_count || 0,
|
||||
afterTokens: 0,
|
||||
compressed: null,
|
||||
})
|
||||
break
|
||||
case 'compression.completed': {
|
||||
const afterTokens = (e as any).contextTokens || (e as any).afterTokens || 0
|
||||
setCompressionState({
|
||||
compressing: false,
|
||||
messageCount: (e as any).totalMessages || 0,
|
||||
beforeTokens: (e as any).beforeTokens || 0,
|
||||
afterTokens,
|
||||
compressed: (e as any).compressed ?? false,
|
||||
error: (e as any).error,
|
||||
})
|
||||
if ((e as any).contextTokens != null) target.contextTokens = (e as any).contextTokens
|
||||
break
|
||||
}
|
||||
case 'abort.started':
|
||||
setAbortState({ aborting: true, synced: null })
|
||||
break
|
||||
case 'abort.completed':
|
||||
setAbortState({ aborting: false, synced: (e as any).synced ?? false })
|
||||
break
|
||||
case 'approval.requested':
|
||||
setPendingApproval({ ...e, session_id: sid })
|
||||
break
|
||||
case 'approval.resolved':
|
||||
clearPendingApproval({ ...e, session_id: sid })
|
||||
break
|
||||
case 'clarify.requested':
|
||||
setPendingClarify({ ...e, session_id: sid })
|
||||
break
|
||||
case 'clarify.resolved':
|
||||
clearPendingClarify({ ...e, session_id: sid })
|
||||
break
|
||||
case 'run.failed':
|
||||
addAgentErrorMessage(sid, e.error)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (activeSessionId.value === sid) activeSession.value = target
|
||||
if (!data.isWorking && !(data.queueLength && data.queueLength > 0)) {
|
||||
cleanup()
|
||||
activeAssistantMessageId = null
|
||||
updateSessionTitle(sid)
|
||||
}
|
||||
}
|
||||
|
||||
// Send run via Socket.IO and listen to streamed events — all closures capture `sid`
|
||||
const ctrl = startRunViaSocket(
|
||||
runPayload,
|
||||
@@ -1694,6 +1795,7 @@ export const useChatStore = defineStore('chat', () => {
|
||||
cleanup()
|
||||
},
|
||||
undefined,
|
||||
{ onReconnectResume: applyReconnectResume },
|
||||
)
|
||||
|
||||
if (!isBridgeSlashCommand || isBridgeCompressCommand) {
|
||||
|
||||
Reference in New Issue
Block a user