Commit Graph

1369 Commits

Author SHA1 Message Date
nesquena-hermes cebca4700b Merge pull request #1708 from nesquena/fix/1707-workspace-name-click
fix(workspace): preserve single-click open + double-click rename on filename (#1707)
2026-05-05 09:16:42 -07:00
nesquena-hermes b5e8e67d71 fix(workspace): preserve single-click open + double-click rename on filename (#1707)
Closes #1707 — single-click on a workspace tree filename did nothing.

#1698 was a regression where the filename's dblclick rename handler was
unreachable because the row's el.onclick (openFile) fired synchronously
on the first click. The fix in #1702 stopped click propagation on nameEl
— but that broke single-click activation entirely (#1707): clicking the
filename now did nothing, you had to click the icon or row whitespace
to open the file.

Restored fix preserves both intents via a 300ms debounced delegator:

  let _nameClickTimer = null;
  nameEl.onclick = (e) => {
    e.stopPropagation();
    if (_nameClickTimer) { clearTimeout(_nameClickTimer); _nameClickTimer = null; }
    _nameClickTimer = setTimeout(() => {
      _nameClickTimer = null;
      if (typeof el.onclick === 'function') el.onclick(e);
    }, 300);
  };
  nameEl.ondblclick = (e) => {
    e.stopPropagation();
    if (_nameClickTimer) { clearTimeout(_nameClickTimer); _nameClickTimer = null; }
    // ... existing rename body
  };

Single-click on nameEl schedules a setTimeout that calls el.onclick(e)
after the dblclick threshold passes (300ms — matches the OS dblclick
threshold on most platforms). Double-click cancels the pending timer
and triggers the existing rename input.

Cost: 300ms latency on file-open clicks. Acceptable trade for keeping
rename reachable on single-click.

Also updated tests/test_workspace_tree_rename.py to accept both the
pre-#1707 (pure stopPropagation) and post-#1707 (debounced delegator)
shapes — the original assertion was too narrow and would have rejected
the correct fix.

9 new regression tests in tests/test_1707_workspace_filename_click.py:
  - 6 source-level static-analysis checks on the patched handler shape
  - 3 behavioral tests via Node VM (synthesize click → 300ms delay,
    click → dblclick within tick → assert rename mounts + openFile
    is not called).

7 of 9 tests fail on master pre-fix (verified); all 9 pass after.
2026-05-05 16:13:58 +00:00
nesquena-hermes 4daa23874a Merge pull request #1707 from nesquena/stage-301
v0.51.4 — 10-PR full-sweep batch
v0.51.4
2026-05-05 08:56:38 -07:00
Nathan Esquenazi 451c946a30 chore(release): stamp v0.51.4 — 10-PR full-sweep batch
10 PRs (3 surfaces additions, 7 fixes):
- #1644 model picker chip + group count (@bergeouss, closes #1425)
- #1684 update network failures UX (@Michaelyklam, closes #1321)
- #1685 Codex spark models (@Michaelyklam, closes #1680)
- #1689 normalize profile base homes (@Michaelyklam, refs #749)
- #1693 adaptive title refresh deadlock (@ai-ag2026)
- #1701 normalize update banner URL (@Michaelyklam, closes #1691)
- #1702 workspace double-click rename (@Michaelyklam, closes #1698)
- #1703 cache invalidation on auth-store drift (@Michaelyklam, closes #1699)
- #1704 markdown fence lengths (@Michaelyklam, closes #1696)
- #1706 multi-image paste fix (@Michaelyklam, closes #1697)

Tests: 4477 → 4503 (+26). Opus: SHIP, 7/7 verification clean.

Co-authored-by: Michael Lam <Michaelyklam1@gmail.com>
Co-authored-by: ai-ag2026 <noreply@github.com>
Co-authored-by: bergeouss <noreply@github.com>
2026-05-05 15:54:12 +00:00
Nathan Esquenazi 2a838ee95a Stage 301: PR #1706 2026-05-05 15:49:28 +00:00
Michael Lam 8c8e2d3573 fix: keep multi-image paste attachments 2026-05-05 08:45:14 -07:00
Nathan Esquenazi e5927c6d0a Stage 301: PR #1704 2026-05-05 15:41:44 +00:00
Nathan Esquenazi debb4c5282 Stage 301: PR #1702 2026-05-05 15:41:43 +00:00
Nathan Esquenazi 8e7a9b1632 Stage 301: PR #1684 2026-05-05 15:41:43 +00:00
Nathan Esquenazi 651cd294d4 Stage 301: PR #1644 2026-05-05 15:41:43 +00:00
Nathan Esquenazi a66feb2661 Stage 301: PR #1703 2026-05-05 15:41:43 +00:00
Nathan Esquenazi 08ea4fbc05 Stage 301: PR #1685 2026-05-05 15:41:43 +00:00
Nathan Esquenazi bf8b5edc23 Stage 301: PR #1701 2026-05-05 15:41:43 +00:00
Nathan Esquenazi db972afd99 Stage 301: PR #1693 2026-05-05 15:41:43 +00:00
Nathan Esquenazi 9dddb5b1d5 Stage 301: PR #1689 2026-05-05 15:41:43 +00:00
bergeouss 6173d6d0ea fix(ui): inline provider chip + group model count in model picker (#1425)
- Add .model-opt-provider chip (right-aligned, muted) on every model row
  that belongs to a provider group, making same-name models across
  providers visually distinguishable at a glance.
- Add per-group model count to group headings: 'OpenRouter (47)'.
- Add subtle border-top divider between provider groups for visual
  separation during scroll.

Scope: Shape A from #1425 — smallest change, ~15 LOC, no API churn.
Note: Settings model picker is a native <select> and already has optgroup
labels; this targets the custom dropdown used in the composer.

Closes #1425
2026-05-05 15:41:22 +00:00
Michael Lam 1997a48c81 test: keep model cache drift regression hermetic 2026-05-05 08:38:29 -07:00
Michael Lam f76921d322 fix: honor markdown fence lengths 2026-05-05 08:36:17 -07:00
Michael Lam c4ef5b6945 fix: invalidate model cache on auth-store drift 2026-05-05 08:33:44 -07:00
Michael Lam ff232493ce fix: keep workspace rename double-click reachable 2026-05-05 08:33:34 -07:00
Michael Lam dc7ba0c845 fix: normalize update banner repository URLs 2026-05-05 08:29:00 -07:00
Manfred 52e7916cb8 fix: avoid adaptive title refresh session lock deadlock 2026-05-05 12:51:13 +02:00
Michael Lam d51510a7dc fix: keep HTTP update errors out of network recovery 2026-05-05 03:13:55 -07:00
Michael Lam f6a532d7f0 fix: normalize named profile base homes 2026-05-05 00:00:29 -07:00
Michael Lam 0fe3927655 fix: surface Codex spark models 2026-05-04 23:10:36 -07:00
Michael Lam 03949f8093 fix: clarify update network failures 2026-05-04 21:02:03 -07:00
nesquena-hermes 1cde702d47 Merge pull request #1683 from nesquena/stage-300
v0.51.3 — 3-PR follow-up batch (#1671, #1673, #1676)
v0.51.3
2026-05-04 19:43:16 -07:00
Nathan Esquenazi 353033eb8d chore(release): stamp v0.51.3 — 3-PR follow-up batch (#1671, #1673, #1676)
CHANGELOG.md: full v0.51.3 entry covering 3 PRs + test-fragility fix
ROADMAP.md: bump version + test count to 4477
TESTING.md: bump version + test count to 4477

Independent review: Opus advisor on stage-300 diff (1050 LOC).
7/7 verification questions verified clean. Verdict: SHIP.
0 MUST-FIX, 0 SHOULD-FIX.
2026-05-05 02:41:24 +00:00
Nathan Esquenazi fb8487f1f0 fix(test): _run_node uses stdin instead of -e argv (sessions.js >128KB)
tests/test_session_lineage_collapse.py invokes 'node -e <source>' where
<source> embeds the entire static/sessions.js content. Linux's
MAX_ARG_STRLEN is 131,072 bytes per argv arg; sessions.js plus the test
scaffolding now exceeds that limit, producing OSError(Argument list too
long).

Switching to 'node' with source via stdin removes the limit. No behavioral
change to the tests themselves — they still exercise the same JS functions
on the same input data.
2026-05-05 02:36:10 +00:00
test 449f37ebd8 Stage 300: PR #1673 — feat: show LLM Gateway routing metadata by @Michaelyklam 2026-05-05 02:27:24 +00:00
test 32f37d3d78 Stage 300: PR #1676 — Add Hermes agent heartbeat alert by @Michaelyklam 2026-05-05 02:27:24 +00:00
test 51e46def4c Stage 300: PR #1671 — feat: add active provider quota status by @Michaelyklam 2026-05-05 02:27:23 +00:00
Michael Lam c94ec31dec feat: show LLM Gateway routing metadata 2026-05-05 02:26:55 +00:00
Michael Lam 22df075b8a feat: add active provider quota status 2026-05-05 02:26:52 +00:00
Michael Lam 960e45f77f feat: add agent heartbeat alert 2026-05-05 02:25:06 +00:00
nesquena-hermes fcc83284e3 Merge pull request #1682 from nesquena/stage-299
v0.51.2 — 3-PR follow-up + sidebar scroll hotfix
v0.51.2
2026-05-04 19:22:03 -07:00
Nathan Esquenazi e095ed90be chore(release): stamp v0.51.2 — 3-PR follow-up + #1669 scroll hotfix
CHANGELOG.md: full v0.51.2 entry covering 3 PRs + sidebar scroll hotfix
ROADMAP.md: bump version + test count to 4457
TESTING.md: bump version + test count to 4457

Independent review: Opus advisor on stage-299 diff (1336 LOC).
6/6 verification questions verified clean. Verdict: SHIP.
0 MUST-FIX, 2 SHOULD-FIX absorbed in-release (bounded WIKI walk +
URL scheme guard).
2026-05-05 02:19:56 +00:00
Nathan Esquenazi e2748fe961 Apply Opus pre-release SHOULD-FIX (absorbed in stage-299)
Per Opus advisor on stage-299:

1. Bounded WIKI_PATH walk + forbidden-root guard (api/routes.py)
   - _LLM_WIKI_MAX_FILES = 10000 caps rglob iteration (prevents hangs on
     symlink loops or pathologically-large trees)
   - _LLM_WIKI_FORBIDDEN_ROOTS blocklist refuses '/' '/etc' '/usr' '/var'
     '/opt' '/sys' '/proc' even if WIKI_PATH is misconfigured to point
     at them
   - Self-DoS prevention: /api/wiki/status fires on every Insights tab
     open via Promise.all, and unbounded rglob would block the endpoint

2. URL-scheme guard for docs_url interpolation (static/panels.js)
   - rawDocsUrl is regex-validated against /^https?:\/\//i before being
     interpolated into the <a href=> attribute
   - esc() HTML-escapes but doesn't validate URL scheme; docs_url is
     server-controlled today but the contributor scaffolded it for
     potential config-driven use, so future-proof against javascript:
     scheme XSS

6 regression tests in tests/test_stage299_opus_fixes.py pin both fixes.
2026-05-05 02:15:25 +00:00
Nathan Esquenazi 4e9ec6f191 fix(sidebar): scroll jumps back to 0 on small lists (≤80 sessions) — #1669 follow-up
PR #1669 added DOM virtualization to renderSessionListFromCache() with two issues
for lists below the virtualization threshold (≤80 rows):

1. The unconditional scroll listener triggered renderSessionListFromCache() on
   every rAF, rebuilding the entire list DOM on every scroll event.
2. After each rebuild, scrollTop was only restored when virtualWindow.virtualized
   was true (i.e. total > 80). For lists ≤ 80 rows, scrollTop dropped to 0 on
   every scroll event, producing a 'scroll keeps jumping back' feel.

Fix:
- Always restore scrollTop after re-render when listScrollTopBeforeRender > 0
  (regardless of virtualized flag).
- Short-circuit _scheduleSessionVirtualizedRender when total <=
  SESSION_VIRTUAL_THRESHOLD_ROWS (saves wasteful rebuild on small lists).

Live verified on a 56-session sidebar: scrollTop holds across animation frames.
3 regression tests pin the fix shape.
2026-05-05 02:02:54 +00:00
test 136d858963 Stage 299: PR #1587 — Filter low-value CLI agent sessions by @franksong2702 2026-05-05 01:54:08 +00:00
test df8ee6a8ad Stage 299: PR #1662 — feat(logs): add Logs tab MVP by @Michaelyklam 2026-05-05 01:53:56 +00:00
test 0d1d0e71ac Stage 299: PR #1664 — Add LLM Wiki status panel MVP by @Michaelyklam 2026-05-05 01:53:09 +00:00
Frank Song d76ef2a2b6 Cover CLI compression lineage filtering 2026-05-05 01:52:42 +00:00
Frank Song 8981d33543 Fix CLI session CI compatibility 2026-05-05 01:52:42 +00:00
Frank Song 79d0762d8c Filter low-value CLI agent sessions 2026-05-05 01:52:42 +00:00
Michael Lam af1c628292 feat: add logs tab MVP 2026-05-05 01:51:05 +00:00
Michael Lam 2684d6fa98 feat: add LLM Wiki status panel 2026-05-05 01:48:32 +00:00
nesquena-hermes e23ba59df2 Merge pull request #1681 from nesquena/stage-298
v0.51.1 — 11-PR contributor batch from @Michaelyklam
v0.51.1
2026-05-04 18:42:28 -07:00
Nathan Esquenazi 58d141b8d6 chore(release): stamp v0.51.1 — 11-PR @Michaelyklam batch + Opus pass
CHANGELOG.md: full v0.51.1 entry covering all 11 constituent PRs
ROADMAP.md: bump version + test count to 4429
TESTING.md: bump version + test count to 4429

Independent review: Opus advisor on stage-298 diff (4749 LOC).
6/6 security/correctness questions verified clean. Verdict: SHIP.
0 MUST-FIX, 0 SHOULD-FIX. Two polish notes deferred to follow-up.
2026-05-05 01:40:36 +00:00
test 3699e83c43 Stage 298: PR #1677 — feat: link official Hermes dashboard by @Michaelyklam 2026-05-05 01:29:49 +00:00