Skip to content

fix: bypass service worker cache for subpath API routes#1278

Closed
Michaelyklam wants to merge 1 commit intonesquena:masterfrom
Michaelyklam:fix/sw-subpath-api-cache
Closed

fix: bypass service worker cache for subpath API routes#1278
Michaelyklam wants to merge 1 commit intonesquena:masterfrom
Michaelyklam:fix/sw-subpath-api-cache

Conversation

@Michaelyklam
Copy link
Copy Markdown
Contributor

@Michaelyklam Michaelyklam commented Apr 29, 2026

Thinking Path

  • Hermes WebUI should keep the browser state in sync with server-side sessions, especially after creating a new chat.
  • The sidebar gets its chat list from /api/sessions, so that endpoint must always reflect current server state.
  • The service worker was correctly avoiding cache for root-mounted API routes like /api/* and /health.
  • When the app is deployed under /hermes/, those same requests become /hermes/api/* and /hermes/health.
  • Those subpath requests did not match the service-worker API bypass check and could fall through to cache-first behavior.
  • This PR fixes the cache bypass so subpath-mounted API/session requests are network-only, which keeps the sidebar list fresh after new chat creation.

What Changed

  • Updated static/sw.js so API/health requests are treated as network-only when Hermes WebUI is mounted under a path prefix:
    • /api/...
    • /health
    • /hermes/api/...
    • /hermes/health
  • Added regression coverage in tests/test_service_worker_api_cache.py for subpath API cache exclusion.

Why It Matters

Without this fix, creating a new chat can succeed server-side while the sidebar still shows a stale cached session list in the browser. Users then have to refresh or clear cache to see the chat they just created, which makes the WebUI feel unreliable even though the backend already created the session correctly.

This keeps session list reads fresh while preserving the service worker's static-asset caching behavior.

Verification

Manual verification:

  • Confirmed locally in the deployed WebUI that new chats appear in the sidebar immediately without clearing browser cache.

Automated verification:

/home/michael/.hermes/hermes-agent/venv/bin/python -m pytest \
  tests/test_service_worker_api_cache.py \
  tests/test_empty_session_no_disk_write.py -q

git diff --check origin/master...HEAD

Result:

10 passed

Risks / Follow-ups

  • Low risk: the change is limited to service-worker route classification for API/health requests.
  • Static assets remain cache-first; only dynamic API/health routes bypass the cache.
  • If additional deployment prefixes are introduced later, the service-worker API detection should stay prefix-aware rather than checking only one hard-coded mount path.

Model Used

AI assisted.

  • Provider: OpenAI via Hermes Agent
  • Model: gpt-5.5
  • Notable tool use: terminal/git/gh CLI for repository inspection and PR updates; file tools for drafting PR body text.

@nesquena-hermes
Copy link
Copy Markdown
Collaborator

Thanks for this fix!

What this does: Updates static/sw.js to treat API and health requests as network-only even when the WebUI is mounted under a subpath (e.g., /hermes/). Without this, a service worker deployed under a prefix would fall through to cache-first behavior for /hermes/api/* requests, causing the sidebar session list to show stale data after a new chat is created.

Scope of changes:

  • static/sw.js — extended API/health route detection to cover both root-mounted (/api/, /health) and subpath-mounted (/hermes/api/, /hermes/health) URLs
  • tests/test_service_worker_api_cache.py — regression coverage for subpath cache exclusion; 10 tests passing

Things to verify before merge:

  • The fix hard-codes /hermes/ as the subpath prefix. If deployments can use arbitrary path prefixes (e.g., /assistant/ or /app/), this approach will still miss those. A more robust approach would check whether the URL contains /api/ or /health at any path segment boundary, or read the prefix from a runtime config injected into sw.js. If /hermes/ is the only supported subpath, this is fine as-is.
  • Confirm that static assets under /hermes/static/... are still correctly handled by the cache-first path and are not accidentally caught by the new check.

Low-risk change with focused scope. The bug it fixes is real and reproducible.

@nesquena-hermes
Copy link
Copy Markdown
Collaborator

✅ Merged into release branch — included in PR #1285 (v0.50.240). Thanks for the contribution!

nesquena-hermes added a commit that referenced this pull request Apr 30, 2026
## Release v0.50.240

Batch release of 13 PRs that passed full triage + code review + test suite (3199 tests, 0 failures).

---

### Added

- **Compact tool activity mode** (`simplified_tool_calling`, default on) — groups tool calls and thinking traces into a single collapsed "Activity" disclosure card per assistant turn. Also adds a new **Calm Console** theme with earth/slate palette and serif prose. @Michaelyklam#1282
- **PDF first-page preview** — `MEDIA:` `.pdf` files render a canvas thumbnail via PDF.js CDN (4 MB cap). **HTML sandbox iframe** — `.html`/`.htm` files render inline in a sandboxed `<iframe srcdoc>` (256 KB cap). 10 i18n keys × 7 locales. @bergeouss#1280, closes #480 #482
- **Inline Excalidraw diagram preview** — `.excalidraw` files render as pure SVG (no external deps; rectangles, ellipses, diamonds, text, lines, arrows, freehand; 512 KB cap). @bergeouss#1279, closes #479
- **Inline CSV table rendering** — fenced `csv` blocks and `MEDIA:` CSV files render as scrollable HTML tables with auto-separator detection. @bergeouss#1277, closes #485
- **Inline SVG, audio, and video rendering** — SVG as `<img>`, audio as `<audio controls>`, video as `<video controls>`. @bergeouss#1276, closes #481
- **Batch session select mode** — multi-select sessions for bulk Archive/Delete/Move. 11 i18n keys × 7 locales. @bergeouss#1275, closes #568
- **Collapsible skill category headers** — click to collapse/expand without re-render; state persists across filter cycles. @bergeouss#1281
- **`providers.only_configured` setting** — opt-in flag to restrict the model picker to explicitly configured providers. @KingBoyAndGirl#1268
- **OpenCode Go model catalog** — adds Kimi K2.6, DeepSeek V4 Pro/Flash, MiMo V2.5/Pro, Qwen3.6/3.5 Plus. @nesquena-hermes#1284, closes #1269

### Fixed

- **Profile `TERMINAL_CWD` TypeError** — `_build_agent_thread_env()` helper merges env before `_set_thread_env()` call. @hi-friday#1266
- **Service worker subpath cache bypass** — regex now matches `/api/*` under any mount prefix. @Michaelyklam#1278
- **SSE client disconnect leaks** — `TimeoutError`/`OSError` treated as clean disconnects; server backlog 64, threads daemonized; session list renders before saved-session restore. @KayZz69#1267
- **i18n locale corrections** — Korean MCP strings (23), Chinese MCP strings (23), zh-Hant missing keys (41), de missing keys (229). @bergeouss#1274, closes #1273

---

### Test results

```
3199 passed, 2 skipped, 3 xpassed in 72.79s
```

### PRs on hold (not included)

#1265 (draft), #1271 (superseded by #1266), #1272 (skipped XSS tests), #1232 (partial test run), #1222 (review questions open), #1134 (live-server tests), #1132 (superseded by #1134), #1108 (negative UX review), #1084 (empty description)
@nesquena-hermes
Copy link
Copy Markdown
Collaborator

Shipped in release v0.50.240 (PR #1285). Thanks!

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