fix: converge remote run state on persisted terminal messages

After a managed SSH disconnect the renderer kept showing the remote
Agent as processing even though the recovered task had already been
persisted as completed. Local streaming copies shadowed the persisted
terminal state in mergePersistedConversations, and recovery completion
never asked the renderer to re-read conversations.

- Prefer the persisted terminal state over a local streaming message
- Settle active runs whose messages already reached a persisted terminal
  state and release the conversation queue once
- Refresh conversations on window focus and visibility changes
- Publish a conversation change before recovery reports completed/failed
This commit is contained in:
mesalogo
2026-09-04 16:54:35 +08:00
parent 670171ce5d
commit d180f63abd
4 changed files with 354 additions and 34 deletions
+14
View File
@@ -6229,6 +6229,20 @@ describe('registerIpcHandlers agent terminal state', () => {
})
)
)
// The renderer converges on the persisted terminal state by re-reading
// conversations, so the change notice must land before `completed`.
const sendCalls = harness.webContents.send.mock.calls
const completedIndex = sendCalls.findIndex(
([channel, payload]) =>
channel === ipcChannels.remoteProjectRecoveryProgress &&
(payload as { stage?: string }).stage === 'completed'
)
expect(completedIndex).toBeGreaterThan(0)
expect(
sendCalls
.slice(0, completedIndex)
.some(([channel]) => channel === ipcChannels.conversationsChanged)
).toBe(true)
await harness.dispose()
})
+4
View File
@@ -1935,12 +1935,16 @@ export function registerIpcHandlers(
for (const task of tasks) {
await recoverRemoteTask(task, requestId)
}
// Recovery may terminalize the task without a trailing checkpoint;
// let the renderer converge on the persisted terminal state.
publishConversationChange()
publishRemoteProjectRecovery({
projectId,
requestId,
stage: 'completed'
})
} catch (error) {
publishConversationChange()
publishRemoteProjectRecovery({
projectId,
requestId,