v0.51.15 — 4-PR batch (#1762, #1767, #1769, #1770)#1777
Merged
nesquena-hermes merged 10 commits intomasterfrom May 7, 2026
Merged
v0.51.15 — 4-PR batch (#1762, #1767, #1769, #1770)#1777nesquena-hermes merged 10 commits intomasterfrom
nesquena-hermes merged 10 commits intomasterfrom
Conversation
…:thinking suffixes (#1744) The previous approach of prepending 'openrouter/' to the model ID in the catalog was incorrect — it only masked the symptom while regressing the config_provider=openrouter codepath. The root cause is in resolve_model_provider(): rsplit(':', 1) on '@openrouter:tencent/hy3-preview:free' yields provider='openrouter:tencent/hy3-preview' and model='free', because the ':free' suffix collides with the @Provider:model grammar. Fix: after rsplit, validate that the extracted provider hint is a known provider (in _PROVIDER_MODELS, _PROVIDER_DISPLAY, or starts with 'custom:'). If not, fall back to split(':', 1) so trailing suffixes stay attached to the model ID. This fixes all current and future OR models with colon-suffixed tags (:free, :beta, :thinking, :nitro, etc.) without catalog changes. Also adds regression tests for the affected models and edge cases. Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
…/hy3-preview:free by @bergeouss
Issue #1764 asked for a much larger surface (Reveal + Copy-path on every UI surface that references a file path, plus Rename in session menus). Per Nathan's curation we ship only the three highest-leverage pieces in this PR — they cover the three concrete user-visible frictions Cygnus reported, and leave the broader sweep for follow-up. ## 1. Copy file path in workspace tree right-click menu The tree's right-click already had Rename and Reveal in File Manager. Reveal is slow when the user just wants the path string for a terminal/editor — and there was no Copy-path action anywhere. Added "Copy file path" between Reveal and Delete. It POSTs to a new `/api/file/path` endpoint that resolves the relative tree-rooted path into the absolute on-disk path (the frontend can't compute it because only the server knows the workspace root) and writes the result to the OS clipboard via `navigator.clipboard.writeText()`. Falls back to the legacy execCommand pattern on browsers where the modern Clipboard API is gated. The new endpoint deliberately does NOT require the target to exist: copy-path on a recently-deleted file is still useful (paste into a terminal to investigate). `safe_resolve` continues to gate path traversal — the test suite pins this with a `../../../../../etc/passwd` attempt that 400s. ## 2. Rename in session three-dot menu Cygnus's specific ask: double-click rename in the sidebar is timing- sensitive — the first click frequently registers as "open the chat" before the second click arrives, so users open the conversation when they meant to rename it. Putting Rename in the menu eliminates the timing entirely. Added Rename as the FIRST item in `_openSessionActionMenu` (above Pin). It reuses the existing `startRename` closure attached to each session row — no duplicated state, no second API call out of band with the double-click path. Mechanism: the row builder now stores `el._startRename = startRename` and `el.dataset.sid = s.session_id`, so the menu can find the row by data-sid and call its closure directly. This keeps all the `_renamingSid`/`oldTitle`/`applyTitle` bookkeeping single-sourced. Read-only imported sessions skip the menu item via the same `_isReadOnlySession` gate the closure already uses. ## 3. Reveal-failed toast includes the resolved server-side path Cygnus posted a screenshot of a "Failed to reveal: not found" toast that dropped the path entirely. Without it the user can't tell which file the system expected — useful when a stale session row still references a deleted file. Server-side fix in `_handle_file_reveal`: instead of returning `bad(handler, "File not found", 404)`, return `bad(handler, f"File not found: {target}", 404)` where target is the resolved absolute path. Frontend toast also defends against err with no .message: `(err.message||err)` instead of `err.message` alone. Verified live: a missing-file reveal now produces: Failed to reveal: File not found: /home/hermes/workspace/missing-xyz.txt Cygnus's exact diagnostic-friction is gone. ## Tests * tests/test_1764_context_menu_essentials.py (new) - 13 source-level pinning tests - 6 live HTTP behaviour tests against the conftest test server * tests/test_1466_sidebar_cancel_clarify.py - Two assertion-window bumps (3200→4400, 3600→4800) to accommodate the new Rename action prepended to _openSessionActionMenu. The test relied on a fixed-byte-window function-body slice — comments added explaining why the bumps were needed. * All 9 locales got translations for the 5 new keys (copy_file_path, path_copied, path_copy_failed, session_rename, session_rename_desc) — locale parity tests pass. ## Verification Full pytest suite: 4671 passed, 2 skipped, 3 xpassed (matches pre-change baseline). Live browser verification on port 8789: - Right-click .git folder in workspace tree → menu shows Rename / Reveal in File Manager / Copy file path / Delete (red). - Click Copy file path → clipboard gets "/home/hermes/workspace/.git", toast confirms "File path copied to clipboard". - Open session three-dot menu → Rename conversation appears first with pencil icon, followed by Pin / Move / Archive / Duplicate / Delete in the same order as before. - Trigger reveal on a non-existent file → toast reads "Failed to reveal: File not found: /home/hermes/workspace/<filename>". The resolved server-side path is now visible in the failure. Refs #1764.
Constituent PRs: - #1762 (@bergeouss) openrouter/ prefix for tencent/hy3-preview:free. Closes #1744. - #1767 (@Michaelyklam) use spawn for manual cron subprocesses. Closes #1754. AUTO-FIX applied: 2 tests skip on dev machines with editable hermes_agent install (the spawn child resolves the real cron.scheduler first instead of the fake one). Tightened detector to use importlib.util.find_spec origin check per Opus stage-309 SHOULD-FIX. - #1769 (@nesquena-hermes, APPROVED by @nesquena) three context-menu essentials from #1764: Reveal-in-finder, Copy-path, Open-with-system. - #1770 (@Michaelyklam) surface Codex usage exhaustion errors. Closes #1765. Tests: 4662 → 4694 collected (+32). 4687 passed, 4 skipped (2 dev-only + 2 prong-2 noise), 3 xpassed, 0 failed in 135s. Pre-release verification: - All 4 PRs CI-green individually. - node -c clean on all 4 changed JS files. - 11/11 browser API endpoints PASS. - Pre-stamp re-fetch: all PR heads match local rebases. - Opus advisor: SHIP, all 5 verification questions clean, 0 MUST-FIX, 2 SHOULD-FIX (one absorbed: detector tightening; one filed as #1776 follow-up: custom provider + :free suffix edge case in #1762). Closes #1744, #1754, #1764, #1765.
This was referenced May 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v0.51.15 — 4-PR batch (cron spawn migration, context menu, codex quota, model prefix)
Constituent PRs
tencent/hy3-preview:free. Closes OpenRouter modeltencent/hy3-preview:freefails with API key not found error in WebUI #1744. One edge case filed as Custom provider + :free suffix mis-resolves in resolve_model_provider() (PR #1762 follow-up) #1776 follow-up (custom provider +:freesuffix).spawnfor manual cron subprocesses. Closes Migrate cron subprocess from fork to spawn (PR #1746 follow-up) #1754 (architectural follow-up from v0.51.12). One-line context changefork→spawnplus +207 LOC of regression coverage. Auto-fix applied: 2 tests skip on dev machines with editable hermes_agent install; tightened detector to useimportlib.util.find_specorigin check per Opus.safe_resolve(), all shell-outs use list-formsubprocess.Popen(no shell=true).quota_exhaustedSSE event distinguishes quota from rate-limit; runtime cleanup preserved; fix: preserve pending user turn on stream errors #1760 user-turn materialization runs before pending-clear.Tests
4662 → 4694 collected (+32). 4687 passed, 0 failed.
Pre-release verification
api/routes.py(fix: use spawn for manual cron subprocesses #1767+feat(ux): three high-leverage context-menu essentials from #1764 #1769) andstatic/ui.js(feat(ux): three high-leverage context-menu essentials from #1764 #1769+fix: surface Codex usage exhaustion errors #1770) auto-merged cleanly (different functions).Closes
tencent/hy3-preview:freefails with API key not found error in WebUI #1744 (model prefix)