Commit Graph

28 Commits

Author SHA1 Message Date
nesquena-hermes
7556ea0e04 docs: v0.49.0 final — test count 697, add #287 and #289 entries
All three PRs now merged:
- #285: first-run onboarding wizard
- #287: self-update git pull diagnostics
- #289: skip flaky redaction test in agent-less envs

Final test count: 697 (up from 679)

Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-12 00:23:06 -07:00
nesquena-hermes
f9663d2f1d docs: bump to v0.49.0 — onboarding wizard release
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-11 23:41:10 -07:00
nesquena-hermes
cbc3c01604 docs: v0.48.2 release notes — provider mismatch warning
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-11 21:26:34 -07:00
nesquena-hermes
afa540a222 docs: v0.48.0 release notes — gateway session sync
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-11 20:54:21 -07:00
nesquena-hermes
c677893105 docs: v0.47.1 release notes — Spanish locale
- CHANGELOG: v0.47.1 entry for Spanish locale (PR #275)
- ROADMAP: header updated v0.47.0 → v0.47.1, 645 → 648 tests; sprint row added
- TESTING.md: test count 645 → 648
- static/index.html: version v0.47.0 → v0.47.1

Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-11 20:08:34 -07:00
nesquena-hermes
b86ace6ce3 v0.47.0: dialogs, session menu, /skills, mobile fixes, mobile QA suite
* fix: custom provider with slash model name no longer rerouted to OpenRouter (#255)

When base_url is configured in config.yaml, resolve_model_provider() now
trusts the configured provider/base_url entirely and skips the slash-based
OpenRouter heuristic. Fixes google/gemma-4-26b-a4b with provider:custom
being silently routed to OpenRouter, resulting in 401 errors.

Fixes #230

* test: mobile layout regression suite — 14 tests for every QA run (#254)

Adds tests/test_mobile_layout.py with 14 static regression tests that run
on every QA pass to catch mobile layout breakage before it reaches prod.
Covers: breakpoints at 900px/640px, right panel slide-over CSS, mobile
overlay, bottom nav, files button, profile dropdown z-index, chip overflow,
workspace close, 100dvh, 44px touch targets, 16px font-size on textarea.

* feat: /skills slash command lists and filters available Hermes skills (#257)

Adds /skills [query] command to commands.js. Fetches from /api/skills,
groups by category (alphabetically sorted), displays as a formatted
assistant message. Optional query filters by name, description, or category.
i18n keys added for en, de, zh, zh-Hant. 1 regression test added.

Fixes #248

* feat: shared app dialogs replace native confirm()/prompt() calls (#251)

Adds showConfirmDialog() and showPromptDialog() helpers to ui.js, backed
by a themed #appDialogOverlay. Replaces all 11 native browser confirm/prompt
call sites across panels.js, sessions.js, ui.js, workspace.js.

Supports: danger mode, keyboard focus trap (Tab/Escape/Enter), focus restore,
ARIA roles, mobile-responsive stacked buttons at 640px. i18n for en/de/zh/zh-Hant.
5 new tests in test_sprint33.py verify markup, CSS, helpers, and absence of
native dialog calls.

Extracted from PR #242.

* fix: Android Chrome mobile — workspace panel close + profile dropdown (#256)

Fix #247: toggleMobileFiles() now shows/hides the mobile overlay when
toggling the right workspace panel. New closeMobileFiles() helper closes
the panel with correct overlay state tracking. Overlay onclick calls both
closeMobileSidebar() and closeMobileFiles(). Mobile-only close button (x)
added to workspace panel header.

Fix #246: profile dropdown uses position:fixed;top:56px;right:8px at
max-width:900px, escaping the overflow-x:auto stacking context that was
clipping it on Android Chrome.

Fix applied during review: closeMobileSidebar() now checks if the right
panel is still open before hiding the overlay, preventing the overlay from
disappearing when only the sidebar is closed.

Fixes #247 Fixes #246

* feat: session ⋯ action dropdown replaces per-row buttons (#252)

Replaces the 5 per-row hover action buttons (pin/move/archive/duplicate/trash)
with a single ⋯ trigger that opens a positioned dropdown menu. Menu has full
keyboard (Escape), click-outside, scroll, and resize-reposition handling.
Position:fixed prevents sidebar clipping.

5 actions: Pin/Unpin, Move to project, Archive/Unarchive, Duplicate, Delete
(danger style). Each with icon and descriptive subtitle.

Updated test_sprint16.py: test_sessions_js_uses_action_menu_not_per_row_buttons
asserts the new trigger and menu functions exist, old per-row classes are gone.

Extracted from PR #242.

* docs: v0.47.0 release notes, bump version, update test counts (645)

---------

Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-11 12:19:12 -07:00
nesquena-hermes
c357ed9b74 docs: fix stale TESTING.md footer (v0.36/440 -> v0.46.0/624)
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-11 10:27:12 -07:00
nesquena-hermes
27c2fd6c08 v0.46.0: security, Docker UID/GID, model discovery, i18n, cancel fix
* fix: decode HTML entities before markdown processing + zh/zh-Hant translations (#239)

Adds decode() helper in renderMd() to fix double-escaping of HTML entities
from LLM output (e.g. &lt;code&gt; becoming &amp;lt;code&amp;gt; instead
of rendering). XSS-safe: decode runs before esc(), only 5 entity patterns.

Also adds 40+ missing zh (Simplified Chinese) translation keys and a new
zh-Hant (Traditional Chinese) locale with 163 keys.

Fix applied: removed duplicate settings_label_notifications key in both
zh and zh-Hant locales.

Fixes #240

* fix: restore custom model list discovery with config api key (#238)

get_available_models() now reads api_key from config.yaml before env vars:
  1. model.api_key
  2. providers.<active>.api_key / providers.custom.api_key
  3. env var fallbacks (HERMES_API_KEY, OPENAI_API_KEY, etc.)

Also adds OpenAI/Python User-Agent header and a regression test covering
authenticated /v1/models discovery.

Fixes users with LM Studio / Ollama custom endpoints configured in
config.yaml whose model picker silently collapsed to the default model.

* feat: Docker UID/GID matching to avoid root-owned .hermes files (#237)

Adds docker_init.bash with hermeswebuitoo/hermeswebui user pattern so
container files match the host user UID/GID. Prevents .hermes volume
mounts from being owned by root when using a non-root host user.

Configure via WANTED_UID and WANTED_GID env vars (default 1000/1000).
Readme updated with setup instructions.

Fix applied: removed duplicate WANTED_GID=1000 line in docker-compose.yml
that was overriding the ${GID:-1000} variable expansion.

* security: redact credentials from API responses and fix credential file permissions (#243)

Adds response-layer credential redaction to three endpoints:
  - GET /api/session — messages[], tool_calls[], and title
  - GET /api/session/export — download also redacted
  - SSE done event — session payload in stream
  - GET /api/memory — MEMORY.md and USER.md content

Adds api/startup.py with fix_credential_permissions() at server startup.
Adds 13 tests in tests/test_security_redaction.py.

Merged with #237 container detection changes in server.py.

* fix: cancel button now interrupts agent and cleans up UI state (#244)

Wires agent.interrupt() into cancel_stream() so the backend actually
stops tool execution when the user clicks Cancel, rather than only
stopping the SSE stream while the agent keeps running.

Changes:
  - api/config.py: adds AGENT_INSTANCES dict (stream_id -> AIAgent)
  - api/streaming.py: stores agent in AGENT_INSTANCES after creation,
    checks CANCEL_FLAGS immediately after store (race condition fix),
    calls agent.interrupt() in cancel_stream(), cleans up in finally block
  - static/boot.js: removes stale setStatus(cancelling) call
  - static/messages.js: setBusy(false)/setStatus('') unconditionally on cancel

Race condition fix: after storing agent in AGENT_INSTANCES, immediately
checks if CANCEL_FLAGS[stream_id] is already set (cancel arrived during
agent init) and interrupts before starting. Check is inside the same
STREAMS_LOCK acquisition, making it atomic.

New test file: tests/test_cancel_interrupt.py with 6 unit tests.

* docs: v0.46.0 release notes, bump version, update test counts

---------

Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-11 10:17:52 -07:00
nesquena-hermes
02e6e768e6 docs: v0.45.0 release notes + roadmap/sprint plan updates
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-10 11:47:04 -07:00
nesquena-hermes
1e27940535 docs: v0.44.1 release notes, version bump, correct test counts
- static/index.html: v0.44.0 → v0.44.1
- CHANGELOG.md: add [v0.44.1] entry for unskip fix; clarify v0.44.0 test
  count was 579/595 at that tag (595/595 after unskip)
- TESTING.md: 579 passing, 16 skipped → 595 passing, 0 skipped

Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-10 10:56:37 -07:00
nesquena-hermes
4947a6b0c3 v0.44.0: approval fix, login CSP, update diagnostics, Lucide icons
* fix: approval pending check broken by stale has_pending import (#228)

api/routes.py imported has_pending/pop_pending from tools.approval, but the
agent module renamed has_pending to has_blocking_approval (checks gateway
queue, not _pending dict) and removed pop_pending. The import fell through
to fallback lambdas that always returned False, making GET /api/approval/pending
always return {pending:null} even after a successful inject_test.

Fix: check _pending directly under _lock — same dict submit_pending writes to.
Stale imports removed.

Before: 554 pass, 1 fail | After: 555 pass, 0 fail

* fix: move login JS into external file, remove inline handlers (#226)

Login page used inline onsubmit/onkeydown handlers and an inline <script>
block — all blocked by strict script-src CSP, causing silent login failure.

Fix: extract doLogin() and Enter key listener into static/login.js (served
from /static/, already a public path). Form uses id='login-form' and
data-* attributes for i18n strings instead of injected JS literals.
Also guards res.json() parse with try/catch so non-JSON error bodies
(e.g. HTTP 500) show the password-error fallback instead of 'Connection failed'.

Fixes #222.

* fix: improve update error messages when pull fails (#227)

_apply_update_inner() ran git pull --ff-only and returned only raw stderr
on failure, making all failure modes indistinguishable.

Fix: explicit git fetch before pull; if fetch fails, returns human-readable
network error. Diverged history and missing upstream tracking branch each
get distinct messages with exact recovery commands. Generic fallback
truncates to 300 chars and shows sentinel when git produces no output.

Also adds tests/test_update_checker.py with 13 tests covering all 4 new
diagnostic code paths (0 tests existed before).

Fixes #223.

* fix: stabilize 30s terminal approval prompt visibility (#225)

Adds minimum 30-second visibility guard for the approval card using
_approvalVisibleSince, _approvalHideTimer, and a signature fingerprint
to deduplicate repeated poll ticks.

Fix: respondApproval() and all stream-end paths (done/cancel/apperror/
error/start-error) now call hideApprovalCard(true) so the card hides
immediately when the user responds or the session ends. The 30s guard
only applies to mid-session poll ticks where the approval is still live
but briefly absent.

Adds 11 structural tests covering the new timer variables, force
parameter, force-on-respond, force-on-stream-end, and poll-loop
no-force behavior.

* feat: replace emoji icons with self-hosted Lucide SVG icons (#221)

Replaces all sidebar/button emoji icons with SVG paths from Lucide bundled
in static/icons.js (no CDN dependency). Adds li(name) function returning
inline SVG geometry from a hardcoded whitelist — unknown keys return '' so
dynamic server-supplied names never inject arbitrary SVG.

Changes:
  - static/icons.js: new file with 21 icon paths + li() renderer
  - static/index.html: all nav/action buttons now use li() icons
  - static/ui.js: toolIcon(), fileIcon() use li() for tool/file icons
  - static/messages.js: cancelStream button uses SVG square stop icon
  - .gitignore: adds node_modules/ entry

Verified: all 35 onclick= functions exist in JS, all 21 li() calls
reference defined icons, applyBotName() selectors intact, version
label present, no removed IDs referenced by JS.

* docs: v0.44.0 release notes, bump version, update test counts

---------

Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-10 10:02:28 -07:00
nesquena-hermes
4d68fb31d4 docs: v0.40.2 release — approval UI, 547 tests (#188)
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-08 20:17:14 -07:00
nesquena-hermes
7e6fec1c85 docs: sweep TESTING.md, SPRINTS.md, ROADMAP.md to v0.39.0 / 499 tests
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-07 22:33:08 -07:00
nesquena-hermes
ccabdf9882 docs: update testing plan version coverage to v0.38.6 (#167)
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-06 23:15:56 -07:00
nesquena-hermes
70a486ddef docs: sweep sprint and testing counts to v0.38.6 (#166)
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-06 23:15:21 -07:00
nesquena-hermes
cd598c896a docs: v0.37.0 release notes, version bump, test count (465 tests) (#144)
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-06 11:19:19 -07:00
nesquena-hermes
89891c65c8 docs: v0.36.3 version bump and test count update (449 tests) (#137)
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-06 08:21:04 -07:00
nesquena-hermes
e1c2e7e3d6 docs: fix stale 433 test counts to 440
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-05 14:55:04 -07:00
nesquena-hermes
c6017f461b docs: v0.36.2 release notes and version bump
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-05 13:59:45 -07:00
nesquena-hermes
3ca7f08b59 docs: sweep markdown for v0.36
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-05 10:00:45 -07:00
nesquena-hermes
853b23cd14 docs: README screenshot refresh + full markdown sweep (v0.34.3, 433 tests, Sprint 26 completed)
* Revise images and enhance layout description in README

Updated images and added new content to the layout section.

* docs: markdown sweep -- v0.34.3, 433 tests, Sprint 26 completed, custom themes row restored

- THEMES.md: restore custom themes row removed by PR #105
- ROADMAP.md: bump version/tests to v0.34.3/433; mark themes [x]; add v0.34/v0.34.1/v0.34.2/v0.34.3 to sprint history table
- SPRINTS.md: Sprint 26 marked COMPLETED; version bumped to v0.34.3; horizon sprint updated to Sprint 25 (Desktop)
- TESTING.md: coverage updated to Sprint 26 / v0.34.3; test count corrected to 433; port corrected to 8786

---------

Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-04 22:22:32 -07:00
nesquena-hermes
2e7ce0a341 docs: v0.31.2 release notes and version bump
* docs: v0.31.1 release notes and version bump

* docs: v0.31.2 release notes and version bump

---------

Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-04 17:40:08 -07:00
nesquena-hermes
33fca2383c docs: v0.29 release notes + roadmap/sprint plan updates
- CHANGELOG.md: add v0.29 entry covering all Sprint 23 deliverables
  (token/cost display, subagent cards, skill picker, linked files viewer,
  workspace tree persistence, timestamp fixes, XSS + security fixes)
- ROADMAP.md: update to v0.29, add Sprint 23 to history table, check off
  token/cost, skill linked files, skill picker in cron (3 items closed)
- TESTING.md: update automated test count 415 -> 424
- SPRINTS.md: add Sprint 24 (web polish bug fix pass) and Sprint 25
  (macOS native desktop app) forward plans; remove stale stub entries

Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-03 19:36:18 -07:00
Nathan Esquenazi
28ac04da7d docs: comprehensive markdown update for v0.24
README.md:
- Features section rewritten: added voice input, profiles, auth/security,
  slash commands, mobile responsive, thinking display, session projects,
  workspace tree, code copy, safe HTML rendering sections
- Architecture tree updated with all current files and line counts
- Env var table: added HERMES_WEBUI_PASSWORD
- Test section: updated count (415 tests), corrected pytest command
- Docs section: added SPRINTS.md reference

ARCHITECTURE.md:
- File inventory: added profiles.py, Dockerfile, docker-compose.yml,
  .dockerignore; updated all line counts to current values
- Env vars: added HERMES_HOME to both server-level and per-request sections
- Test files: 21 files, 415 functions (was 17 files, 327)

ROADMAP.md:
- Header: v0.21 -> v0.24, 328 -> 415 tests
- Sprint history table: added Sprints 20-22
- Architecture table: updated line counts and added Docker row
- Feature checklist: marked voice, mobile, profiles as done; reorganized

TESTING.md:
- Header: Sprint 19/v0.21 -> Sprint 22/v0.24, updated test counts
- Footer: same updates
- Added manual test sections for Sprints 20 (voice + send button),
  21 (mobile + Docker), 22 (multi-profile)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:20:43 -07:00
Nathan Esquenazi
2dda99082f docs: fix test count 327->328 in CHANGELOG, TESTING.md, ROADMAP.md
Sprint 19 added 10 new tests (not 9), bringing the total to 328 (not 327).
All 328 tests pass with 0 failures -- the "304 passing, 23 pre-existing
failures" note was stale from an earlier state of the test suite.

Files updated:
- CHANGELOG.md: v0.21 header, tests line, footer
- TESTING.md: automated tests header, footer
- ROADMAP.md: header note, Sprint History table
2026-04-03 13:34:21 +00:00
Nathan Esquenazi
66bd84accb docs: comprehensive update of all markdown files for v0.21
ARCHITECTURE.md:
- 6→7 JS modules (added commands.js), updated all line counts
- Added api/auth.py to file inventory
- Added HERMES_WEBUI_PASSWORD env var
- Added projects.json to state directory listing
- Replaced PORTABILITY.md ref with BUGS.md
- Updated test file references (test_sprint1-19, 327 functions)

ROADMAP.md:
- Version Sprint 17/v0.19 → Sprint 19/v0.21, test count 294→327
- Added Sprint 18 + 19 rows to sprint history table
- Updated architecture table (api/ 2491 lines, JS 3148 lines)
- Added sections: Workspace, Slash Commands, Security, Thinking
- Added Sprint 20-24 to Advanced/Future (voice, mobile, multi-profile,
  desktop, extended commands)

SPRINTS.md:
- Header v0.20→v0.21, 318→327 tests
- "Where we are now" updated from v0.18 to v0.21
- Removed two stale/duplicate "Sprint 18" sections (Voice + Subagent)
- Added completed Sprint 18 (thinking + tree + preview fix)
- Added completed Sprint 19 (auth + security)
- Added planned Sprints 20-24 (voice, mobile, multi-profile, desktop, commands)
- Parity tables fully updated with current Done/Deferred status

CHANGELOG.md:
- Added v0.21 Sprint 19 entry (auth, security headers, 20MB limit)

TESTING.md:
- Header "through Sprint 2" → "through Sprint 19 (v0.21)"
- Added test count and pytest command to header
- Added 9 new manual test sections covering Sprints 11-19
- Updated footer with current stats

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 06:06:00 -07:00
Hermes
7019c25021 Hermes Web UI — Sprints 11-14: multi-provider models, settings, session QoL, alerts, polish
Sprint 11 (v0.13): multi-provider model support, streaming smoothness
- Dynamic model dropdown populated from configured API keys (OpenAI, Anthropic,
  Google, DeepSeek, GLM, Kimi, MiniMax, OpenRouter, Nous Portal)
- Scroll pinning during streaming (no forced scroll when user has scrolled up)
- All route handlers extracted to api/routes.py (server.py now ~76 lines)

Sprint 12 (v0.14): settings panel, SSE reconnect, session QoL
- Settings panel (gear icon) -- persist default model and workspace server-side
- SSE auto-reconnect on network blips
- Pin/star sessions to top of sidebar
- Import session from JSON export

Sprint 13 (v0.15): cron alerts, background errors, session duplicate, tab title
- Cron completion alerts: toast per completion + unread badge on Tasks tab
- Background agent error banner when a non-active session errors mid-stream
- Session duplicate button
- Browser tab title reflects active session name

Sprint 14 (v0.16): Mermaid diagrams, file ops, session archive/tags, timestamps
- Mermaid diagram rendering inline (dark theme, lazy CDN load)
- File rename (double-click in file tree) and create folder
- Session archive (hide without deleting, toggle to show)
- Session tags -- #hashtag in title becomes colored chip + click-to-filter
- Message timestamps (HH:MM on hover, full date as tooltip)

Test suite: 224 tests across 14 sprint files + regression gate, 0 failures.
2026-03-31 07:02:47 +00:00
Nathan Esquenazi
a4e2174c29 Hermes WebUI v0.1.0 — initial public release 2026-03-30 20:40:19 -07:00