github nesquena/hermes-webui v0.50.296
v0.50.296 — 3-PR batch (TPS in headers + session save mode + Codex OAuth onboarding)

latest releases: v0.51.3, v0.51.2, v0.51.1...
5 hours ago

Release v0.50.296 — 3-PR batch (TPS in headers + session save mode + Codex OAuth onboarding)

3 PRs from 1 contributor (@Michaelyklam). Closes #1406, #1617; refs #1362.

What ships

#1640 — show TPS in assistant message headers (closes #1617)

UX gate APPROVED by @aronprins (May 04 19:24 UTC) after the design discussion narrowed to default-off + Preferences toggle. Per-turn TPS rendered in the assistant message header (not the global titlebar) when show_tps is enabled. Default-off — no UI change for non-power users. Hot-applies on toggle without page refresh.

Backend now distinguishes real TPS readings from "no real reading available" (no more placeholder 0.0 chips). Live counting switched from character-count-derived to streaming-callback deltas. Final TPS computed from exact final output token usage / backend-measured turn duration when both signals are available.

#1648 — operator config knob for session save timing (closes #1406)

webui.session_save_mode accepts deferred (default — preserves v0.50.230 fix for #1171 orphan-Untitled files) or eager (materializes user message into s.messages before launching agent thread for crash-resilience on the first prompt). Implementation matches @nesquena-hermes's prescribed shape from the #1406 maintainer comment 1:1 — no Settings UI toggle (operator-level only), default stays deferred, threshold is "≥1 user message" not "did new_session() get called". Updates WAL/repair path + streaming context-build path to avoid double-counting the user turn in eager mode.

#1650 — first in-app OAuth flow: OpenAI Codex (refs #1362)

Three new endpoints (POST /api/onboarding/oauth/start, GET /api/onboarding/oauth/poll, POST /api/onboarding/oauth/cancel) with server-owned device-code lifecycle. Browser only sees flow_id, user_code, verification_uri, status — never raw OAuth lifecycle secrets (device_auth_id, code_verifier, authorization_code, access_token, refresh_token). 15-minute flow timeout. Atomic tmp+rename with chmod 0o600 BEFORE rename so final auth.json never has a world-readable window. Profile-scoped storage (writes to active profile's auth.json credential_pool.openai-codex). Allowlist _ALLOWED_ONBOARDING_OAUTH_PROVIDERS = {"openai-codex"}; explicit blocklist for anthropic/claude/nous/qwen/gemini/minimax/copilot (rejected with generic message — no internal triage state leaked).

Anthropic Claude OAuth is the planned v2 per @nesquena-hermes's prescribed roadmap.

Tests

4255 → 4284 passing (+29). 0 regressions. Full suite ~120s.

Pre-release verification

  • Opus advisor on stage-296 combined diff: SHIP verdict. All 14 verification questions cleared, with focused OAuth security audit on #1650:
    • In-memory _OAUTH_FLOWS is the right shape (persistence would require writing sensitive device_auth_id + code_verifier to disk — strictly more attack surface than losing transient flows on restart)
    • Lock NOT held during network IO (concurrent flows don't block each other)
    • flow_id (UUID4, 128-bit) leakage analyzed — worst case is poll/cancel another flow, no credential exposure
    • Allowlist fail-closed (any truthy unknown string rejected)
    • chmod-before-rename correctly implemented per the prior security-fix pattern
    • Sensitive fields scrubbed on every terminal status transition via _drop_sensitive_flow_fields
    • No internal triage state in error messages
  • Two minor follow-ups absorbed in-release per <20-LOC defensive policy:
    • _get_active_hermes_home() exception fallback now logs a logger.warning(...) so silent profile-corruption fallback is observable in logs
    • Codex credential pool find-loop accepts both source == "manual:device_code" (current code) AND source == "oauth_device" (legacy) so users with prior creds get their entry updated in-place rather than accumulating stale duplicate pool entries
  • #1640 @aronprins UX-gate APPROVED.
  • #1648 implements @nesquena-hermes's prescribed shape from the #1406 maintainer comment 1:1.
  • #1650 implements @nesquena-hermes's prescribed shape from the #1362 maintainer comment 1:1.
  • JS syntax: 5 modified .js files clean.
  • Browser API sanity: 11/11 endpoints OK on stage server.

Author

Trust boundary note

This release ships the first user-facing OAuth flow in the WebUI. Token storage path, atomic write semantics, chmod timing, server-side flow state, and the allowlist/blocklist pattern are all in scope for security reviewers. The Hermes Agent CLI's auth.json format is the source-of-truth contract — both the WebUI and CLI write the same credential_pool.openai-codex shape, so credentials added via either surface are usable by either surface.

Don't miss a new hermes-webui release

NewReleases is sending notifications on new releases.