Commit Graph

1611 Commits

Author SHA1 Message Date
AJV20 1b48643f63 feat: support passkey-only auth 2026-05-25 00:14:38 +00:00
AJV20 c60ff543b5 feat: add passkey sign-in 2026-05-25 00:14:38 +00:00
Lumen Yang d0992730a9 fix: preserve repeated state rows in replay delta 2026-05-25 00:10:27 +00:00
Lumen Yang 5934c2fe8a fix: address context replay review feedback 2026-05-25 00:10:27 +00:00
Lumen Yang c616c8e788 fix: cap live tool prompt estimates 2026-05-25 00:10:27 +00:00
Lumen Yang 50c69713cc fix: reconcile state db delta after context 2026-05-25 00:10:27 +00:00
Lumen Yang 15cde132f3 fix: dedupe replayed context summaries 2026-05-25 00:10:27 +00:00
ai-ag2026 8a2f11c770 fix(chat): log sanitized client sse diagnostics
(cherry picked from commit 749ca6e18c5e307fbf7e7fb5fffce97249545017)
2026-05-25 02:06:42 +02:00
ai-ag2026 2f1ca959f1 fix(chat): classify interrupted response causes
(cherry picked from commit 5c1e802cd6ee8565da74c7ffe57e6407fe21bf02)
2026-05-25 02:06:42 +02:00
ai-ag2026 efe3d7c296 fix(chat): avoid false restart wording for interrupted responses
(cherry picked from commit ef8fd879682aeb729a7b7afa1e7c46478ca5ebb6)
2026-05-25 02:06:42 +02:00
nesquena-hermes e5533ea0e4 Merge pull request #2547 from AJV20/fix/webui-context-parity
fix(chat): align WebUI context with messaging sessions
2026-05-24 23:12:27 +00:00
nesquena-hermes 767a9cd06d Merge pull request #2527 from AJV20/feat/webui-notes-sources
feat(memory): show third-party notes sources
2026-05-24 23:11:54 +00:00
nesquena-hermes d42253bca3 Merge pull request #2873 from Charanis/codex/webui-launcher-env-pr
[1/7] Preserve WebUI launcher environment
2026-05-24 23:09:28 +00:00
nesquena-hermes 6f94a44745 Merge pull request #2868 from AJV20/feat/pwa-sidebar-swipe
feat: add PWA sidebar edge swipe
2026-05-24 23:08:30 +00:00
AJV20 d7b98d87cd Merge remote-tracking branch 'origin/master' into maint/pr-2547
# Conflicts:
#	CHANGELOG.md
2026-05-24 17:48:09 -04:00
AJV20 24979c8af1 Merge remote-tracking branch 'origin/master' into maint/pr-2527
# Conflicts:
#	CHANGELOG.md
2026-05-24 17:48:09 -04:00
AJV20 cf92aa5cc1 Merge remote-tracking branch 'origin/master' into maint/pr-2868
# Conflicts:
#	CHANGELOG.md
2026-05-24 17:48:07 -04:00
AJV20 6e2991f45a Merge remote-tracking branch 'origin/master' into maint/pr-2865
# Conflicts:
#	CHANGELOG.md
2026-05-24 17:48:06 -04:00
Charanis f0b0854773 fix: preserve webui launcher environment
(cherry picked from commit 2297ab4db8)
2026-05-24 21:49:21 +02:00
hermes-agent c9bc21f394 Stage 406: in-stage test fixes + CHANGELOG for v0.51.130
- Patch tests/test_issue2762_state_sync_profile_kwarg.py::_read_session
  helper to query the real state.db schema (sessions.id PRIMARY KEY,
  not sessions.session_id). Was always broken — the test never matched
  any actual schema. Fix: SELECT id AS session_id + WHERE id = ?
- Patch tests/test_session_metadata_fast_path.py::test_failed_boot_model_catalog_prime_is_retryable
  to accept both populateModelDropdown() and populateModelDropdown({preferProfileDefaultOnFreshBoot:true})
  signatures (sibling-collision with #2726).
- Patch tests/test_model_default_boot_precedence.py::test_boot_model_dropdown_explicitly_requests_profile_default_precedence
  to accept either the original allowBootSavedModelOverride variable
  name OR the post-#2716-cherry-pick stateToApply equivalent
  (!window._defaultModel?savedState:null gate).
- Stamp CHANGELOG for v0.51.130 (Release DB).
2026-05-24 19:17:59 +00:00
AJV20 b0f7a7bdff feat: add PWA sidebar edge swipe 2026-05-24 15:14:28 -04:00
AJV20 7af7370be6 Merge remote-tracking branch 'origin/master' into fix/session-personality-default
# Conflicts:
#	CHANGELOG.md
2026-05-24 15:05:29 -04:00
hermes-agent 7a84c81dda Stage 406: PR #2673 — Add scoped workspace Artifacts tab by @AJV20 (closes #2655) 2026-05-24 18:58:59 +00:00
hermes-agent 4f20cbd6ca Stage 406: PR #2673 — Add scoped workspace Artifacts tab by @AJV20 (closes #2655)
Cherry-picked via 3-way apply onto stage HEAD.
Resolved workspace.js conflict: kept master's #2716 sessionId-capture
stale-session guard (closure-scoped sessionId check after await), AND
added PR's renderSessionArtifacts() call to refresh the new Artifacts
tab when the file tree updates. Wrapped in typeof check for defense.

Co-authored-by: AJV20 <abdielvc@me.com>
2026-05-24 18:58:37 +00:00
hermes-agent d9b2dd5019 Stage 406: PR #2726 — fix(model): keep boot default precedence non-destructive by @starship-s
Cherry-picked via 3-way apply onto stage HEAD (post-Release-A/B/C1).
Resolved boot.js conflict: took PR's parameterized
populateModelDropdown({preferProfileDefaultOnFreshBoot:true}) call
(the whole point of #2726) on top of master's #2716 boot path.

Co-authored-by: starship-s <starship-s@github.users.noreply.github.com>
2026-05-24 18:58:37 +00:00
hermes-agent fd1c4eaeaf Stage 406: PR #2827 — fix(state-sync): pass profile explicitly so background-thread DB writes hit the right state.db (#2762) by @Koraji95-coder 2026-05-24 18:57:40 +00:00
AJV20 9bd595de40 fix: avoid stamping display personality on sessions 2026-05-24 14:57:37 -04:00
hermes-agent 2b6ed07c95 Stage 405: i18n parity + brittle-counter fixes for sibling-PR collisions
- Add Turkish translations for 16 settings_aux_* / settings_label/desc_auxiliary_models
  keys that #2680 added against the 10-locale set (pre-#2772 Turkish baseline).
- Bump test_auxiliary_models_settings.py::test_all_locales_have_auxiliary_keys
  from count == 11 to count == 12 (one per locale, now including tr).
2026-05-24 18:36:13 +00:00
hermes-agent c15148f925 Stage 405: PR #2842 — feat: polish installed PWA startup by @AJV20
Cherry-picked via 3-way apply of net delta against stage HEAD. All 8 files
applied cleanly including the new static/pwa-startup.js.

Co-authored-by: AJV20 <abdielvc@me.com>
2026-05-24 18:28:52 +00:00
hermes-agent a86b378036 Stage 405: PR #2680 — feat: add Auxiliary Models settings card by @mccxj
Cherry-picked via 3-way apply (rebase had failed on static/index.html
conflict when applied via rebase commit chain; 3-way of the net delta
against stage HEAD applied cleanly).

Co-authored-by: mccxj <mccxj@github.users.noreply.github.com>
2026-05-24 18:28:26 +00:00
Michael Lam dd7648d56c feat(runtime): wire runner route selection harness 2026-05-24 18:26:55 +00:00
hermes-agent 2419b3a0a2 Stage 404: PR #2830 — fix(sessions): keep pin state authoritative by @franksong2702 (closes #2821)
Agent reviewer 'LGTM. Ship it.'
- Bug A fix: _session_field helper handles dict-vs-object snapshot in pin-limit check
- Bug B fix: removed stale client-side pinLimitReached short-circuit
- Bug C recovery: renderSessionList() on pin/unpin failure refreshes from server

Co-authored-by: franksong2702 <146128127+franksong2702@users.noreply.github.com>
2026-05-24 18:08:42 +00:00
hermes-agent 9d95ba0b92 Stage 404: PR #2716 — Performance optimizations by @dobby-d-elf
nesquena APPROVED 2026-05-22. Cherry-picked onto post-v0.51.127
master via 3-way apply. Resolved api/routes.py conflict: master had
the inline correctness fix from the deep-review iteration; PR
refactors it into _metadata_only_message_summary() helper. Took the
helper AND added profile= threading (post-#2827 master adds
profile-aware state.db reads). Kept master's pre-existing
test_api_session_reload_drops_stale_cached_user_tail_after_saved_assistant
alongside the PR's new test_metadata_fast_path_matches_reconciliation_for_restamped_replays.

Co-authored-by: dobby-d-elf <dobby.the.agent@gmail.com>
2026-05-24 18:08:41 +00:00
hermes-agent 130be3db1d Stage 403: Opus pre-release fixes (1 MUST-FIX + 3 SHOULD-FIX)
MUST-FIX:
- tests/test_2735_open_in_vscode.py: bump expected open_in_vscode locale
  counter from 10 to 11 (Turkish locale added in #2772). The bump fell
  out of an in-rebase test edit but never got committed; tagging without
  this would have shipped a failing test in the release commit.

SHOULD-FIX inline:
- api/updates.py: case-D drift in _select_apply_compare_ref. The original
  #2855 fix used latest_tag in the past-tag predicate; the check side
  uses current_tag (HEAD's nearest reachable tag) plus a 'behind == 0'
  gate. They drift when HEAD is on an OLDER release tag with commits on
  top AND a NEWER tag exists ('case D'): check correctly suggests
  advancing to the newer tag, but apply fell through to origin/<branch>.
  Mirror the check-side predicate exactly. Adds regression test
  test_select_apply_compare_ref_case_d_older_tag_with_commits_and_newer_tag_exists.
- static/messages.js: post-await race guard in _restoreSettledSession.
  stream_end without preceding 'done' enters the settlement path, awaits
  /api/session, then sets _streamFinalized=true. If a late 'done' event
  arrives during that await, it sees _streamFinalized still false and
  double-runs the finalize. The guard returns early when done won the
  race, avoiding double renderMessages() + double notification.
- server.py: CORS preflight Access-Control-Allow-Methods now includes PUT.
  #2776 wired PUT into the router for /api/mcp/servers/{name} but didn't
  update the OPTIONS response. Same-origin only in practice, but cosmetic
  completeness for CORS-aware deployments.

Opus advisor verdict: all 5 risk areas reviewed, 1 MUST-FIX + 3 SHOULD-FIX
all addressed inline. Net: +69/-9, no new architecture, no behavior risk.
2026-05-24 17:42:06 +00:00
Uğur Murat Altıntas d4603b096d fix(i18n): correct double-escaped ellipsis in Turkish locale
Replace \\u2026 with \u2026 (and fix \\u2192/\\u2713) in the tr block
so ellipsis renders as U+2026 instead of literal backslash-u text.
Add a regression test guarding against double-escaped unicode sequences.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-24 17:13:34 +00:00
Uğur Murat Altıntas 6c811dcef5 fix(i18n): address Turkish locale review feedback
Fix Copilot review issues in the tr locale: Korean string leaks,
placeholder order, stray quotes, broken {provider} tags, duplicate
English voice keys overriding translations, and remaining TODO strings.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-24 17:13:34 +00:00
Uğur Murat Altıntas c77936ff81 feat(i18n): add Turkish (tr) locale support
Add a complete Turkish locale to the WebUI and login page so users can
select Türkçe in Settings, with speech recognition via tr-TR.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-24 17:13:34 +00:00
Rory Ford 7be9a26018 feat: PATCH /api/mcp/servers/{name} — enable/disable toggle
Add `PATCH /api/mcp/servers/{name}` endpoint that accepts `{"enabled": bool}`,
updates `mcp_servers.<name>.enabled` in config.yaml, and calls `reload_config()`.
Mirrors the existing DELETE pattern.

Also wire the previously-defined-but-unrouted `_handle_mcp_server_delete` into
`handle_delete`, and `_handle_mcp_server_update` into a new `handle_put` +
`do_PUT` in server.py — fixing a pre-existing bug where those handlers existed
but were never reachable over HTTP.

UI: add a toggle button in each MCP server row in the system settings panel
(panels.js). Clicking it calls PATCH and reloads the list. Toggle button is
styled with `.mcp-toggle-enabled` / `.mcp-toggle-disabled` CSS classes. The
`toggle_supported` flag in the list response is now `True`.

i18n: add 5 new keys (`mcp_enable_server`, `mcp_disable_server`,
`mcp_enabled_toast`, `mcp_disabled_toast`, `mcp_toggle_failed`) to all 9
non-English locales (English values as placeholder translations).

Tests: add `TestMcpToggle` class with 7 tests covering disable, enable,
404-not-found, empty name, missing field, response payload, and URL-encoded name.
Update `test_empty_config` and visibility panel assertions to reflect
`toggle_supported: True` and the new toggle button in panels.js.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 17:13:32 +00:00
nesquena-hermes 5d0d2bd0bf fix(updates): apply path must follow check-side fall-through past the latest tag
Fixes #2846. After PR #2758 (the #2653 fix) the update check correctly
falls through to the branch comparison when HEAD has moved past the
latest `v*` tag — so the banner reports the real commit count against
`origin/<branch>`. But `_select_apply_compare_ref` was never updated to
mirror that decision: as long as any `v*` tag exists, it returns
`tags[0]`, even when HEAD is far past it.

Result for everyone running hermes-agent past `v2026.5.16` (i.e. anyone
on agent master between tagged releases):

1. Banner: `Agent (origin/main): 254 updates available` ← correct
2. User clicks Update Now
3. `_select_apply_compare_ref` picks `v2026.5.16` because tags exist
4. `git pull --ff-only origin v2026.5.16` — no-op (HEAD is already past it)
5. `_schedule_restart()` fires anyway, server bounces
6. Next check still reports 254 behind — banner reappears unchanged

`apply_force_update` had the same bug, except worse: `git reset --hard
v2026.5.16` would have actively rewound the user's checkout 254 commits.

The root cause is the same bug class as #2653 — two parallel paths
(`_check_repo_release` and `_select_apply_compare_ref`) that should make
the same decision but didn't. Pre-fix, the "is HEAD past the latest
tag?" predicate lived inline inside `_check_repo_release` only.

Fix
---

Extract `_head_is_past_latest_tag(path, current_tag)` and have both
paths consult it. When HEAD is past the latest tag:

- check path:  release check returns None → branch check runs (#2653,
  unchanged behaviour, just refactored)
- apply path:  falls through to upstream / `origin/<branch>`, never the
  stale tag (#2846, new behaviour)

Tests
-----

- `test_select_apply_compare_ref_uses_tag_when_head_is_on_tag` —
  unchanged behaviour pinned: HEAD exactly on tag → advance to tag.
- `test_select_apply_compare_ref_falls_through_when_head_is_past_tag` —
  the #2846 repro: HEAD = v2026.5.16 + 608 commits → advance to
  `origin/main`, not the tag.
- `test_select_apply_compare_ref_no_tags_uses_upstream` — unchanged.
- `test_select_apply_compare_ref_no_tags_no_upstream_uses_default_branch`
  — unchanged.
- `test_check_and_apply_paths_agree_when_head_is_past_tag` — symmetry
  test, ensures the two paths can't drift apart again.

All 21 tests in `tests/test_updates.py` pass locally (16 existing + 5
new).

Refs #2846, #2653.
2026-05-24 17:13:32 +00:00
nesquena-hermes 71ba863ce5 fix(terminal): drop PR_SET_PDEATHSIG preexec_fn that killed every Linux shell
Fixes #2853. The `_terminal_shell_preexec_fn` added in `71d8a8fb` called
`prctl(PR_SET_PDEATHSIG, SIGTERM)` so orphaned PTY shells would die when
the WebUI process crashed. But that signal is **per-thread**, not
per-process, and WebUI runs `ThreadingHTTPServer`: every HTTP request is
handled in its own short-lived worker thread.

Flow that broke every Linux user:

1. User clicks the terminal toggle → frontend hits `POST /api/terminal/start`.
2. ThreadingHTTPServer spins up a worker thread to handle that one request.
3. The worker thread calls `subprocess.Popen(..., preexec_fn=...)`.
4. The shell calls `prctl(PR_SET_PDEATHSIG, SIGTERM)` in its preexec_fn.
   Its registered "parent" is now the WebUI worker thread that called Popen.
5. The handler returns its JSON response and the worker thread exits.
6. The kernel sees the pdeathsig-parent thread has died and sends SIGTERM
   to the PTY shell. The shell dies within ~10 ms of being created.
7. The reader loop sees EIO on the master FD, emits `terminal_closed`, and
   the frontend writes `[terminal closed]`.

macOS users were unaffected because `libc.prctl` doesn't exist there —
`ctypes.CDLL(None)` returns a libc handle, `libc.prctl` raises
`AttributeError`, the bare-`except` swallows it, and the shell starts
with no pdeathsig configured.

Empirical verification on this Linux host (real PTY + `subprocess.Popen`
inside a `threading.Thread` that joins immediately):

  with    preexec_fn → proc.poll() == -15 (SIGTERM), master FD returns EIO
  without preexec_fn → proc.poll() == None (alive), master FD returns "HELLO\\r\\n"

Same shell, same PTY, same threading topology as WebUI.

Fix
---

Drop the `preexec_fn` entirely. The orphan-shell-on-crash case the original
PR was navigating is rare for self-hosted single-user installs, and the
existing `atexit.register(close_all_terminals)` + explicit `close_terminal`
paths cover graceful shutdown. A future fix (option B in the issue) can
re-introduce pdeathsig pinned to a long-lived supervisor thread, but that
is a follow-up — this PR is the smallest unbricks-Linux-today change.

Tests
-----

- Invert `test_terminal_shell_uses_parent_death_signal_preexec` →
  `test_terminal_shell_does_not_use_pdeathsig_preexec`: asserts
  `preexec_fn` is NOT in the Popen kwargs.
- Add `test_pty_shell_survives_when_spawning_thread_exits`: spawns a
  real PTY shell via `start_terminal` from a worker thread, waits for
  the worker to join, asserts the shell is still alive after a half-second
  grace window. This is the contract the original tests never exercised.
- Update `test_terminal_module_registers_graceful_shutdown_reaper` to
  refuse re-introduction of the preexec_fn or the `libc.prctl(1, SIGTERM)`
  call (treats either as a regression).

All 27 terminal-related tests pass locally.

Refs #2853
2026-05-24 17:13:31 +00:00
ai-ag2026 a34d5e26c2 fix(chat): settle stream_end without done 2026-05-24 17:10:01 +00:00
AJV20 237bab753a feat: surface live activity timeline (#2847)
Squashed from 2 author commits:
- d2237e23 feat: surface live activity timeline
- eee57ec0 fix: satisfy activity timeline CI guards

Frontend-only telemetry from existing stream events. Replaces empty
Thinking… placeholder with observable run status (Waiting on model /
Waiting on tool result / Working for …). New CSS, new test file.
2026-05-24 16:13:00 +00:00
Frank Song 70402f96f1 fix(workspace): fall back for large markdown previews 2026-05-24 15:52:54 +00:00
Frank Song 99c886c199 fix(workspace): open rendered preview links correctly 2026-05-24 15:52:35 +00:00
Frank Song f1586daa3b fix(cron): surface gateway scheduling guidance 2026-05-24 15:52:35 +00:00
Frank Song 67a204773e fix(csrf): clarify rejection diagnostics 2026-05-24 15:52:34 +00:00
AJV20 b6f7412b53 Add option to ignore agent updates 2026-05-24 15:52:34 +00:00
Frank Song 618e1a5da8 fix(server): tolerate malformed request logging 2026-05-24 15:52:00 +00:00
Abdul Munim 7999d1c75a feat(workspace): add Open in VS Code action for files and folders (#2735)
Right-click any workspace file, folder, or root now shows
'Open in VS Code' alongside the existing Reveal in File Manager action.

- POST /api/file/open-vscode: resolves path via safe_resolve, finds VS
  Code via shutil.which() with fallbacks for macOS (/usr/local/bin/code,
  app bundle CLI), Linux (/usr/bin/code, /snap/bin/code), and Windows
  (%LOCALAPPDATA% and %PROGRAMFILES% user/system installs). Returns a
  descriptive error if not found rather than a bare OS error.
- Optional vscode block in config.yaml: command (default: code),
  host_path_prefix + container_path_prefix for Docker path mapping.
- i18n: open_in_vscode and open_in_vscode_failed translated in all 10
  locales (it, ja, ru, es, de, zh-CN, zh-TW, pt, ko).
- 26 tests in tests/test_2735_open_in_vscode.py covering source wiring,
  command resolution, i18n completeness, and live endpoint error paths.
2026-05-24 04:26:46 +00:00
Qi d20da832b3 fix(static): tighten cache validators and 304 headers 2026-05-24 04:26:46 +00:00