mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-17 09:41:58 +00:00
fix(desktop): sync new sessions across windows
Broadcast session-list mutations from scratch windows so the main sidebar refreshes without manual reloads.
This commit is contained in:
parent
0f75e9904a
commit
67233d1c2a
4 changed files with 45 additions and 0 deletions
|
|
@ -77,6 +77,7 @@ import {
|
|||
setSessionsLoading,
|
||||
setSessionsTotal
|
||||
} from '../store/session'
|
||||
import { onSessionsChanged } from '../store/session-sync'
|
||||
import { clearSessionTodos, setSessionTodos, todoListActive } from '../store/todos'
|
||||
import { openUpdatesWindow, startUpdatePoller, stopUpdatePoller } from '../store/updates'
|
||||
import { isSecondaryWindow } from '../store/windows'
|
||||
|
|
@ -464,6 +465,17 @@ export function DesktopController() {
|
|||
void refreshSessions()
|
||||
}, [refreshSessions])
|
||||
|
||||
// Another window mutated the shared session list (e.g. a chat started in the
|
||||
// pop-out). Re-pull so the sidebar reflects it. Pop-outs have no sidebar, so
|
||||
// only real windows bother.
|
||||
useEffect(() => {
|
||||
if (isSecondaryWindow()) {
|
||||
return
|
||||
}
|
||||
|
||||
return onSessionsChanged(() => void refreshSessions().catch(() => undefined))
|
||||
}, [refreshSessions])
|
||||
|
||||
// ALL-profiles view pages one profile at a time: fetch that profile's next
|
||||
// page and merge it in place, leaving every other profile's rows untouched.
|
||||
const loadMoreSessionsForProfile = useCallback(async (profile: string) => {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ import {
|
|||
setTurnStartedAt,
|
||||
setYoloActive
|
||||
} from '@/store/session'
|
||||
import { broadcastSessionsChanged } from '@/store/session-sync'
|
||||
import { clearSessionSubagents, pruneDelegateFallbackSubagents, upsertSubagent } from '@/store/subagents'
|
||||
import { setSessionTodos } from '@/store/todos'
|
||||
import { recordToolDiff } from '@/store/tool-diffs'
|
||||
|
|
@ -641,6 +642,9 @@ export function useMessageStream({
|
|||
})
|
||||
|
||||
void refreshSessions().catch(() => undefined)
|
||||
// Sync the freshly-titled row to other windows (e.g. main, when the turn
|
||||
// ran in the pop-out).
|
||||
broadcastSessionsChanged()
|
||||
|
||||
if (compactedTurnRef.current.delete(sessionId)) {
|
||||
shouldHydrate = false
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import {
|
|||
setYoloActive,
|
||||
workspaceCwdForNewSession
|
||||
} from '@/store/session'
|
||||
import { broadcastSessionsChanged } from '@/store/session-sync'
|
||||
import { reportBackendContract } from '@/store/updates'
|
||||
import { isWatchWindow } from '@/store/windows'
|
||||
import type { SessionCreateResponse, SessionInfo, SessionResumeResponse, SessionRuntimeInfo, UsageStats } from '@/types/hermes'
|
||||
|
|
@ -472,6 +473,9 @@ export function useSessionActions({
|
|||
// server later returns its own preview/title and supersedes this.
|
||||
upsertOptimisticSession(created, stored, null, preview?.trim() || null)
|
||||
navigate(sessionRoute(stored), { replace: true })
|
||||
// Other windows (e.g. the main window when this is the pop-out) can't
|
||||
// see this session until they re-pull the shared list.
|
||||
broadcastSessionsChanged()
|
||||
}
|
||||
|
||||
setFreshDraftReady(false)
|
||||
|
|
|
|||
25
apps/desktop/src/store/session-sync.ts
Normal file
25
apps/desktop/src/store/session-sync.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Cross-window session-list sync. Each desktop window is its own renderer
|
||||
// process with its own gateway socket and session store, so a mutation in one
|
||||
// (e.g. a new chat started in the compact pop-out) never reaches another
|
||||
// window. This bus pings every window to re-pull the shared session list; the
|
||||
// data already lives in the backend, the other window just doesn't know to look.
|
||||
const CHANNEL = 'hermes:sessions'
|
||||
|
||||
const channel = typeof BroadcastChannel === 'undefined' ? null : new BroadcastChannel(CHANNEL)
|
||||
|
||||
// A window that mutated the session list (created / titled a chat) tells the
|
||||
// others to refresh. A BroadcastChannel never delivers to its own poster, so the
|
||||
// caller refreshes locally as it already does.
|
||||
export function broadcastSessionsChanged(): void {
|
||||
channel?.postMessage(1)
|
||||
}
|
||||
|
||||
export function onSessionsChanged(handler: () => void): () => void {
|
||||
if (!channel) {
|
||||
return () => {}
|
||||
}
|
||||
|
||||
channel.addEventListener('message', handler)
|
||||
|
||||
return () => channel.removeEventListener('message', handler)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue