Commit Graph

1326 Commits

Author SHA1 Message Date
BonyFish ea3d4ec0b3 feat(cron): dynamic delivery options from API instead of hardcoded select
Replace the hardcoded 4-option deliver dropdown (local/discord/telegram/slack)
with a dynamic select populated from a new GET /api/crons/delivery-options
endpoint that reads _KNOWN_DELIVERY_PLATFORMS from hermes-agent.

Key changes:
- Add GET /api/crons/delivery-options endpoint returning all known platforms
- Frontend loads options asynchronously on first cron form open, with caching
- Enable deliver editing for existing jobs (was previously disabled)
- Include deliver in update payload when editing cron jobs
- Fallback to local-only if API unavailable
- Custom deliver values (e.g. feishu:oc_xxx) shown with * suffix
- Add cron_deliver_custom i18n key to all 12 locales
- Add 5 integration tests for the new endpoint
2026-05-27 10:58:49 +08:00
nesquena-hermes 2d7d2cb31d Merge pull request #2958
# Conflicts:
#	CHANGELOG.md
2026-05-27 00:38:58 +00:00
nesquena-hermes ad4a4e2d62 Merge pull request #2506
# Conflicts:
#	CHANGELOG.md
2026-05-27 00:38:40 +00:00
nesquena-hermes e0dfa0c586 Merge pull request #2792 2026-05-27 00:37:48 +00:00
nesquena-hermes 6c619f9e81 Merge pull request #2970 2026-05-27 00:19:20 +00:00
nesquena-hermes 858a250319 Merge pull request #2899 2026-05-27 00:19:20 +00:00
nesquena-hermes 52e785a2d8 Merge pull request #2902
# Conflicts:
#	CHANGELOG.md
2026-05-27 00:19:20 +00:00
nesquena-hermes 80a9b0fa68 Merge pull request #2985
# Conflicts:
#	CHANGELOG.md
2026-05-27 00:03:02 +00:00
nesquena-hermes f3fbb49ce4 Merge pull request #2983
# Conflicts:
#	CHANGELOG.md
2026-05-27 00:02:47 +00:00
nesquena-hermes f061733c91 Merge pull request #2969
# Conflicts:
#	CHANGELOG.md
2026-05-27 00:02:32 +00:00
nesquena-hermes 825288a590 Merge pull request #2967
# Conflicts:
#	CHANGELOG.md
2026-05-27 00:02:09 +00:00
nesquena-hermes c7e7029ab4 Merge pull request #2950
# Conflicts:
#	CHANGELOG.md
2026-05-26 23:51:39 +00:00
nesquena-hermes 12fb9cac7e Merge pull request #2948
# Conflicts:
#	CHANGELOG.md
2026-05-26 23:51:25 +00:00
ai-ag2026 815df9de76 fix: vendor math and yaml assets for CSP 2026-05-26 23:49:02 +02:00
george-andraws 65cae8f1a5 Improve sidebar chat search highlighting 2026-05-26 14:17:59 -07:00
weiwei83 d0235b7f5a fix: remove dead #composerAttach selector (actual ID is #attachTray) 2026-05-26 21:29:18 +08:00
weiwei83 1c7dfc85b3 refactor: code review cleanup
- Rename _escHandler to _keyHandler (now handles nav keys too)
- Store counter reference (lb._counterEl) to avoid DOM query on every nav
- Remove dead 'let counter = null' and 'hasNav' closure variable
- Use lb._navImages directly in keyboard handler for consistency
- Add null guard on lb.querySelector('img') in _navigateLightbox
- Inline _updateLightboxCounter one-liner
- Fix CSS section comment 'Image lightbox close' → 'Image lightbox'
- Fix CHANGELOG placeholder (#PR → #2967)
2026-05-26 21:28:38 +08:00
weiwei83 84d0d56f53 refactor: address PR review — fix event listener churn and dead code
- _navigateLightbox now reads lb._navIndex / lb._navImages directly
  instead of receiving a closure-captured index and rebuilding the
  keyboard handler on every navigation. No more removeEventListener /
  addEventListener churn.
- Button onclick handlers also read the live lb._navIndex.
- Removed dead backward-compat string-type shim and its unused oldEl
  querySelector.
- Composer attach-tray chips now open single-image lightboxes (no
  sibling detection across staged uploads).
2026-05-26 21:21:30 +08:00
Frank Song 9db0d6869a fix: keep session switch metadata non-blocking 2026-05-26 16:40:35 +08:00
AlexeyDsov 08277fcd9c perf(ui): cache visWithIdx to skip O(N) scan on render window expansion 2026-05-26 11:24:23 +03:00
AlexeyDsov f0dfe116ca perf(ui): limit renderMessages O(N) passes to visible window 2026-05-26 11:24:11 +03:00
AlexeyDsov 755ecb94cd perf(ui): cache renderMd output and lazy Prism.js highlighting 2026-05-26 11:23:50 +03:00
weiwei83 ecf7ca7c60 feat: add prev/next navigation to image lightbox
When multiple images appear in the same message, clicking any image
now opens a lightbox with prev/next navigation buttons (‹ / ›) and
keyboard support (← / →). An image counter (e.g. '3 / 5') is shown at
the bottom of the overlay.

- _openImgLightbox now receives the clicked <img> element to find
  sibling images within the same message container
- New _openImgLightboxWithNav, _navigateLightbox, _updateLightboxCounter
- CSS: .img-lightbox-nav (prev/next buttons), .img-lightbox-counter
- Close button (×), Escape key, and click-outside-to-close preserved
2026-05-26 15:16:03 +08:00
Sanjay Santhanam cf94f2f7c4 docs(docker): promote scheduled-jobs section to H2 + runnable verify command (review feedback from @nesquena-hermes) 2026-05-25 23:11:59 -07:00
Sanjay Santhanam 0211e1e012 fix(providers): pass through server CSRF reason instead of one-size message (review feedback from @nesquena-hermes) 2026-05-25 23:11:11 -07:00
Sanjay Santhanam 6dd6bced67 fix(transcript): preserve subagent accent over tool-card border-left (review feedback from @nesquena-hermes) 2026-05-25 23:10:39 -07:00
Frank Song a9ea56040f Tighten interim progress activity boundaries 2026-05-26 11:32:34 +08:00
Frank Song 26fb71839e fix(chat): keep visible interim progress in timeline 2026-05-26 09:53:55 +08:00
Sanjay Santhanam 655b5f9101 docs(docker): point gateway-not-configured banner at a real fix
Scheduled cron jobs created in the Tasks panel never tick on a
single-container Docker install because the WebUI doesn't run the
gateway daemon itself. The maintainer's analysis on #2785 spells this
out: the gateway ticks the scheduler every 60s, and without it
'Gateway not configured' just sits there.

The Tasks panel already shows a banner explaining this, but doesn't
give the user anywhere to go. Two small docs-shaped changes:

1. Add a 'Scheduled jobs require a gateway daemon' section to
   docs/docker.md under 'What goes wrong' with the two-container
   compose command and a verify step. Cross-linked from the existing
   short paragraph higher up so both entry points land on the same
   fix.

2. Append a 'How to enable scheduled jobs in Docker' link to the
   cron panel banner (loadCronGatewayNotice) pointing at the new
   docs anchor when the gateway is unconfigured. The banner text
   itself is unchanged.

Verified locally by serving the WebUI without a gateway, opening
Tasks, and confirming the banner now shows the new link; clicked it
and confirmed it lands on the new docs section. With the gateway
running the banner stays hidden as before.

Refs #2785
2026-05-25 11:35:24 -07:00
Sanjay Santhanam 51f333fef0 fix(providers): clearer toast on 403 when removing a provider key
The Remove button under Settings -> Providers calls
POST /api/providers/delete, which runs through _check_csrf. When the
CSRF cookie/header pair has drifted (typically a tab opened before the
most recent login or cookie rotation), the server returns 403 with the
string 'Cross-origin request rejected'. That string reads like a
reverse-proxy deployment problem and gives the user no next step (#2572).

Surface a recovery-shaped toast on 403 from this endpoint:
'Session expired. Reload the page and try again.' The underlying
server response is unchanged so logs/diagnostics still see the original
string; only the user-facing toast is replaced for this code path.

Verified locally by patching _check_csrf to return False, clicking
Remove on a provider card, and confirming the toast now reads the new
message instead of the raw cross-origin string.

Refs #2572
2026-05-25 11:28:14 -07:00
Sanjay Santhanam d86e841f0b fix(transcript): make tool cards visually distinct without hover
The tool-card border-subtle was so faint that the cards visually melted
into the surrounding prose once the cursor left the conversation. Bumps
the resting border to --border-muted and adds a 2px left edge so a tool
output row reads as metadata at a glance, even on light skins where
border-subtle is barely visible. Hover still escalates to --border2.

Verified by loading a session with mixed tool calls and assistant prose
on the light theme and confirming the tool cards are now identifiable
without mousing over them.

Refs #2867
2026-05-25 11:22:35 -07:00
nesquena-hermes 7c666d8e4d Merge pull request #2913
# Conflicts:
#	CHANGELOG.md
2026-05-25 17:47:51 +00:00
nesquena-hermes 4a8b29db9e Merge pull request #2928
# Conflicts:
#	CHANGELOG.md
2026-05-25 17:18:02 +00:00
nesquena-hermes f7ff8b5297 Merge pull request #2919
# Conflicts:
#	CHANGELOG.md
2026-05-25 17:02:33 +00:00
nesquena-hermes bf28f400ec Merge pull request #2921
# Conflicts:
#	CHANGELOG.md
2026-05-25 17:02:16 +00:00
nesquena-hermes fdb0ccb392 Merge pull request #2940 2026-05-25 17:02:02 +00:00
nesquena-hermes d86aa6013f Merge pull request #2906 2026-05-25 17:01:47 +00:00
george-andraws fe597c1cdf fix chat upload attachment paths 2026-05-25 09:12:14 -07:00
ai-ag2026 47f6648905 fix(chat): keep one live SSE source per stream 2026-05-25 13:14:55 +02:00
Frank Song cfca26f2e8 Repaint sidebar after session archive or delete 2026-05-25 16:31:15 +08:00
Frank Song 85e13a6121 fix: reserve space for clarify dialogs 2026-05-25 15:58:27 +08:00
ai-ag2026 9e74072bf3 fix(chat): resolve stale compression parent routes 2026-05-25 08:54:46 +02:00
ai-ag2026 3009c0bf71 fix(chat): keep compression tip selected in sidebar 2026-05-25 08:28:12 +02:00
ai-ag2026 21655af09b fix(chat): accept session_id URL parameter 2026-05-25 07:59:21 +02:00
ai-ag2026 17233293ac fix(chat): dedupe uploaded-file pending turns 2026-05-25 06:11:22 +02:00
george-andraws e8d4a15d19 fix: keep underscores literal while streaming 2026-05-24 19:02:58 -07:00
nesquena-hermes 18c94ad324 Merge pull request #2896 — localize third-party notes drawer copy
# Conflicts:
#	CHANGELOG.md
2026-05-25 01:47:24 +00:00
nesquena-hermes e8ab7410df Merge pull request #2893 — reject update apply with no selected target
# Conflicts:
#	CHANGELOG.md
2026-05-25 01:47:23 +00:00
Qi 7bd85405c9 perf(session): cumulative tail-window load for older history
_loadOlderMessages() previously fetched older messages with the legacy
index-cursor page (msg_before=_oldestIdx&msg_limit=30) and prepended
the page to S.messages. After #2716 the backend always runs the full
append-only merge for /api/session?messages=1 — the same merge as a
larger msg_limit on the same call — so we can ask for a larger
authoritative tail window directly instead of stitching pages on the
client.

Behavior

* Default request shape becomes msg_limit=currentLoaded+30. The newly
  exposed head of the response is what the user sees as 'older
  messages'. No new query parameters.
* msg_before remains supported by the backend and is retained in the
  client as a race-fallback path: if the returned tail no longer has
  the currently displayed messages as a suffix (because the session
  appended new messages mid-flight, or merge filtered something), the
  client issues the legacy msg_before page and prepends it instead.
  This preserves correctness under concurrent appends.
* Suffix-continuity uses the existing _sameTranscriptMessage helper,
  which tolerates timestamp drift and content-array reshapes.
* Existing race guards (loadingSessionId, S.session.session_id, and
  the _messagesGeneration snapshot from #1937) are reapplied after
  the fallback await.

Tests

Updated four static-string assertions in the existing scroll/viewport
tests to track the new mutation site (S.messages = nextMessages) and
the new msg_limit=requestedLimit shape, while still asserting that
msg_before remains in the body for the race-fallback path.

  pytest -q
    tests/test_older_history_viewport_preservation.py
    tests/test_parallel_session_switch.py
    tests/test_issue1937_endless_scroll_jumpstart_race.py
    tests/test_session_tail_payload.py
  -> 52 passed
  node --check static/sessions.js -> ok

Notes

Originally part of PR #2835. That PR was closed because of an
architectural conflict with #2716 on a different file (api/models.py
metadata-only path). #2716 left static/sessions.js untouched — this
change applies cleanly on post-#2716 master with no rebase work.
2026-05-25 01:01:45 +00:00
Frank Song d2e4dfabb4 fix: localize external notes drawer copy 2026-05-25 08:51:44 +08:00