Skip to content

fix: import missing Hermes sessions into WebUI chat#528

Open
SulthanZahran1 wants to merge 2 commits into
EKKOLearnAI:mainfrom
SulthanZahran1:fix/incremental-webui-session-sync
Open

fix: import missing Hermes sessions into WebUI chat#528
SulthanZahran1 wants to merge 2 commits into
EKKOLearnAI:mainfrom
SulthanZahran1:fix/incremental-webui-session-sync

Conversation

@SulthanZahran1
Copy link
Copy Markdown

@SulthanZahran1 SulthanZahran1 commented May 7, 2026

Why

WebUI has two session views that do not read from the same database:

  • History reads Hermes' core state.db.
  • Chat reads WebUI's local mirror DB (hermes-web-ui.db).

That means a session created from another browser/device can exist in Hermes core and show up in History, but still be missing from the Chat sidebar unless WebUI imports it into its local DB.

On current main, that import only happens on a completely empty WebUI DB. Once the local DB has any session, startup sync exits early forever. It also only imports api_server sessions, even though WebUI-originated chats are stored in Hermes core with source webui.

Result: cross-device/browser Chat history can silently stop syncing after the first local session exists.

Root cause on current main

syncAllHermesSessionsOnStartup() currently does this:

const hasExistingSessions = countResult && countResult.count > 0

if (hasExistingSessions) {
  logger.info('[session-sync] local DB has %d sessions, skipping Hermes sync', countResult!.count)
  return
}

And the profile sync only queries one source:

const summaries = await listHermesSessionSummaries('api_server', 10000, profile)

So there are two separate problems:

  1. Existing local sessions block all future imports.
  2. webui sessions are never queried/imported.

What this changes

  • Run startup session sync incrementally instead of only when the local DB is empty.
  • Query both Hermes session sources that can back Chat history:
    • webui
    • api_server
  • Use the Hermes session ID as the local mirror session ID.
    • This makes sync idempotent across restarts.
    • Re-running startup sync will not create duplicate mirrored sessions.
  • Add fallback detection for older imports that used random local UUIDs.
    • If an existing local row has the same profile + source + started_at + title, it is treated as already imported.
  • Keep the existing WebUI local DB architecture intact.
    • This does not replace Chat with direct reads from Hermes state.db.
    • It only makes the existing mirror sync behave incrementally.

Stale web app cache cleanup

This PR also adds server-side cache headers for the SPA shell and a cleanup response for legacy service worker URLs.

Reason: while testing this class of WebUI fixes, stale browser assets/service workers can make the deployed app keep running old frontend code even after the backend fix is deployed. The new policy keeps hashed assets cacheable, but prevents / and /index.html from being pinned stale.

Verification

Confirmed the bug still exists on latest origin/main (9fbff08):

  • With one existing local session, startup sync returns early and does not call listSessionSummaries at all.
  • With an empty local DB, startup sync calls listSessionSummaries('api_server', 10000, 'default') only; it never queries webui.

Tested this branch with:

  • npm test -- tests/server/session-sync.test.ts
  • npm run build

Notes

  • No CONTRIBUTING.md or PR template was present.
  • Existing unrelated local-only changes were not included: packages/server/src/services/gateway-bootstrap.ts and docker-compose.override.yml.

@SulthanZahran1 SulthanZahran1 changed the title fix: incrementally sync WebUI chat sessions fix: import missing Hermes sessions into WebUI chat May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants