Commit Graph

1055 Commits

Author SHA1 Message Date
Michael Lam 8ba16ab294 fix: reuse compact live thinking card 2026-05-16 21:44:18 -07:00
nesquena-hermes 573b1e12ad Stage 375: PR #2428 stage-fix #2 — drop angle brackets from pipe-protect set (Opus catch)
Opus advisor review of stage-375 flagged that the protected-bracket set including `<` and `>` caused tables containing comparison operators across adjacent columns to mis-collapse: `| x < 5 | y > 10 |` matched `< ... >` as a bracket pair and stashed the inner pipe, producing one cell instead of two.

Real LLM table output uses angle brackets as comparison operators far more often than as content-grouping pairs, so the safer default is to NOT treat them as a matched pair. Dropped `<` from the opener class and `>` from both closer classes.

Three regression tests added (`TestComparisonOperatorsAcrossColumns` class): `< … >` across columns, `<` alone, `>` alone.
2026-05-17 03:53:29 +00:00
nesquena-hermes d45d4c08b5 Stage 375: PR #2428 stage-fix — hex-escape brace literals in pipe-protect regex + drop apostrophe-stop + add 9 regression tests
PR #2428's iterative _protectPipes regex introduced two issues we caught during stage assembly:

1. The negated character classes [^)\]}'>] added `'` as a stop character. That breaks cells containing string-literal pipes like `('a'|'b')` (Python type-union examples) — they would still mis-split. Dropped the apostrophe-stop.

2. The literal `}` inside the regex character classes confused the brace-counting extractFunc driver in tests/test_renderer_js_behaviour.py, breaking all 45 existing node-driven renderer tests. Rewrote both brace literals as hex escapes (\\x7b and \\x7d) — semantically identical at the regex-engine level but the JS source carries no bare brace glyph.

Also added tests/test_issue2428_table_pipe_protection.py with 9 regression tests covering single-pipe, multi-pipe-in-brackets, apostrophes-with-pipes, and the KaTeX \$...\$ guard.
2026-05-17 03:41:43 +00:00
nesquena-hermes e9c6b7f06c Stage 375: PR #2432 — feat(theme): add Catppuccin appearance skin (Latte + Mocha palettes) by @Michaelyklam (closes #2426)
Co-authored-by: Michael Lam <michael@example.local>
2026-05-17 03:35:19 +00:00
nesquena-hermes 1793aa8c85 Stage 375: PR #2428 — fix(renderer): protect pipes inside brackets from table cell split + KaTeX dollar in tables by @bengdan
Co-authored-by: manji <manji@local>
2026-05-17 03:35:19 +00:00
nesquena-hermes a33cd4195b Stage 374: PR #2431 — fix(chat): render pending assistant placeholder before /api/chat/start returns by @Michaelyklam (fixes #2429)
Co-authored-by: Michael Lam <michael@example.local>
2026-05-17 02:49:35 +00:00
nesquena-hermes 13265b7085 Stage 374: PR #2425 — i18n: add internationalization for Settings Plugins panel by @mccxj
Co-authored-by: BonyFish <mc02cxj@gmail.com>
2026-05-17 02:49:34 +00:00
nesquena-hermes 47c210899e Stage 374: PR #2421 — fix(cache-tokens): surface provider prompt-cache read/write tokens in WebUI usage by @Michaelyklam (fixes #2419)
Co-authored-by: Michael Lam <michael@example.local>
2026-05-17 02:49:34 +00:00
nesquena-hermes 3480e75e13 Stage 372: PR #2413 — feat(quota-chip): add Settings toggle, flip default to off 2026-05-16 23:05:09 +00:00
nesquena-hermes 780bddca04 Stage 372: PR #2411 — fix: preserve named custom provider model selections by @Michaelyklam (fixes #2405) 2026-05-16 23:04:53 +00:00
nesquena-hermes 862d32ce27 Stage 372: PR #2408 — fix: split live Activity groups at auto-compression by @Michaelyklam (fixes #2404) 2026-05-16 23:04:18 +00:00
nesquena-hermes cf23d47e2d fix(stage-371): apply Opus SHOULD-FIX — KaTeX/CSV/diff stay LTR + chip 1px boundary
Opus advisor on stage-371 caught three issues during pre-release review:

1. RTL salvage missed KaTeX math (display equations + inline LaTeX), diff
   blocks, CSV tables (column order must read left-to-right regardless of
   chat direction), and .skill-file-path. The first salvage commit only
   covered pre/code/kbd/samp/tt and tool-call bodies. Added a second
   force-LTR block covering: .katex, .katex-block, .katex-display,
   .katex-html, .katex-inline, .diff-block (+children), .csv-table-wrap,
   .csv-table (+children), .skill-file-path. Severity: KaTeX is the most
   user-visible gap — any user rendering math under RTL would see flipped
   equations.

2. Quota chip @media (max-width:1400px) hide rule conflicted at exactly
   1400px with the existing @media (min-width:1400px) .messages-inner
   rule — chip was hidden AT the wide-desktop boundary where it should
   first appear. Changed to (max-width:1399.98px). Visually verified at
   1400px: chip now correctly visible there.

3. Dead .icon-btn.provider-quota-chip selector — chip never has icon-btn
   class. Removed.

Test added: test_rtl_math_and_tables_stay_ltr (pins the 4 new LTR
surfaces). Also removed dead code in test_rtl_code_blocks_stay_ltr
(unused code_block variable).

Per stage-fix protocol: SHIP-with-followup applied on the stage rather
than the source PR, since #2409 is already merged-into-stage and
nesquena-approved. Stage-371 review-bypass batch path still holds.
2026-05-16 22:22:38 +00:00
nesquena-hermes a4ab7d4d27 Stage 371: PR #2409 — Stuck-PR sweep: salvage RTL chat from #1721 + override quota chip from #2082 by @malulian and @ai-ag2026
Co-authored-by: malulian <malulian@users.noreply.github.com>
Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com>
2026-05-16 22:04:56 +00:00
Hermes Agent b937cf3583 Stage 370: PR #2390 — Fix live progress Activity grouping by @franksong2702
# Conflicts:
#	CHANGELOG.md
2026-05-16 20:21:58 +00:00
Hermes Agent 41f8b77a0b Stage 369: PR #2393 — fix: cap live chat stream transports by @Michaelyklam
# Conflicts:
#	CHANGELOG.md
2026-05-16 20:03:44 +00:00
Hermes Agent 8b4f8b0600 Stage 369: PR #2347 — Preserve live agent timeline across session switches by @franksong2702 2026-05-16 20:03:43 +00:00
Michael Lam 0b64e21264 fix: cap live chat stream transports 2026-05-16 10:27:28 -07:00
Hermes Agent 8f4d6c1431 Stage 368: PR #2391 — fix: reduce browser storage pressure by @Michaelyklam 2026-05-16 17:19:08 +00:00
Hermes Agent 89be2ef458 Stage 368: PR #2387 — fix: guard localStorage quota writes by @Michaelyklam 2026-05-16 17:19:08 +00:00
Hermes Agent a1d048af29 Stage 368: PR #2375 — fix: keep markdown tables block-level by @Michaelyklam 2026-05-16 17:19:04 +00:00
Hermes Agent 1775e5c054 Stage 368: PR #2372 — fix: add i18n support to settings conversation page action buttons by @mccxj 2026-05-16 17:18:27 +00:00
Michael Lam 48b82d57db fix: reduce browser storage pressure 2026-05-16 08:44:04 -07:00
Frank Song 2dfe3ffb42 Fix live progress activity grouping 2026-05-16 23:37:44 +08:00
Michael Lam 3bb8c7b276 fix: guard localStorage quota writes 2026-05-16 07:31:44 -07:00
Michael Lam 2284d42695 fix: interpolate German session time labels 2026-05-16 04:31:48 -07:00
Michael Lam 3cbe206832 fix: keep markdown tables block-level 2026-05-16 02:12:52 -07:00
BonyFish f87e32d0c7 fix: add i18n support to settings conversation page action buttons
- Add data-i18n attributes to JSON, Import tooltip, and Clear button
- Reuse existing 'clear' and 'import' i18n keys for button labels
- Add 'export_session_json', 'export_session_json_tooltip',
  'import_session_json_tooltip', 'clear_conversation_btn_tooltip'
  keys to all 11 locales (en, it, ja, ru, es, de, zh, zh-Hant, pt, ko, fr)
2026-05-16 14:57:01 +08:00
Frank Song e7e45fe98b Stamp live assistant turns at creation 2026-05-16 14:12:08 +08:00
Frank Song 10db8b3bb6 Preserve base Thinking card markup for animation tests 2026-05-16 14:12:08 +08:00
Frank Song faedcab739 Preserve live agent timeline across session switches 2026-05-16 14:12:08 +08:00
Hermes Agent b8d2fca52f Stage 367: PR #2367 — fix: add i18n support to settings sidebar menu items by @mccxj 2026-05-16 05:43:27 +00:00
Frank Song 80be1d08dc Fix Markdown table cell paragraph spacing 2026-05-16 05:43:04 +00:00
Hermes Agent ddf8eb5d54 stage-367: locale-parity fix for settings_tab_plugins (10 locales)
PR #2367 added settings_tab_plugins to English only. The locale-parity
tests (test_chinese_locale.py, test_japanese_locale.py, etc.) require
every English key to exist in all 10 other locales. CI failed on 5 of them.

Adds the key to all 10 non-English locales with translations:
- it: Plugin, ja: プラグイン, ru: Плагины, es/de/pt/fr: Plugins (loanword),
  zh: 插件, zh-TW: 外掛, ko: 플러그인

Co-authored-by: mccxj <mccxj@users.noreply.github.com>
2026-05-16 05:42:53 +00:00
BonyFish 9593380899 fix: add i18n support to settings sidebar menu items
Adds data-i18n attributes to all settings sidebar menu items
(Conversation, Appearance, Preferences, Plugins, System) so they
respect the user's selected locale.

Also adds missing settings_tab_plugins key to English locale.
2026-05-16 13:09:09 +08:00
Frank Song 433ad29939 Fix compression reference card anchoring 2026-05-16 04:25:22 +00:00
Frank Song d94320b4bf Avoid duplicate Thinking echo helper names 2026-05-16 04:07:03 +00:00
Frank Song dd5f3ff9b5 Suppress interim text echoes in Thinking cards 2026-05-16 04:07:03 +00:00
Hermes Agent b293bf8bc5 stage-364: Opus-caught live SSE event_id fix (side-channel approach)
Replace the earlier frontend-reset approach with a backend side-channel
approach that preserves the queue (event, data) tuple shape.

Problem (Opus catch):
- Live SSE frames emitted by _sse() in api/streaming.py:2296 carried no
  'id:' field. Only journal-replay frames (via _sse_with_id) emitted IDs.
- Frontend's _lastRunJournalSeq cursor stayed at 0 during live streaming.
- Mid-stream error → reconnect-to-replay arrived with after_seq=0.
- Server replayed every journaled event from seq 1.
- assistantText (closure-scoped) had accumulated all live tokens already
  → double-rendered output.

Fix:
- api/config.py: STREAM_LAST_EVENT_ID: dict = {} module-level dict.
- api/streaming.py put(): capture journal event_id, write to
  STREAM_LAST_EVENT_ID[stream_id]. Keep queue tuple as (event, data).
- api/routes.py _handle_sse_stream: read STREAM_LAST_EVENT_ID[stream_id]
  at emit time, use _sse_with_id when set.
- api/streaming.py finally block: pop STREAM_LAST_EVENT_ID for cleanup.

Why side-channel instead of 3-tuple:
- Earlier attempt (queue tuple → (event, data, event_id)) broke 4 existing
  tests: test_cancel_interrupt, test_sprint42, test_sprint51,
  test_issue1857_usage_overwrite. These all unpack 'event, data = q.get()'.
- Frontend-reset approach (reset assistantText before replay) broke 3
  other tests: test_smooth_text_fade, test_streaming_markdown,
  test_streaming_race_fix. _wireSSE must NOT reset accumulators because
  legacy reconnect doesn't replay events; only journal-replay does.

Side-channel preserves both invariants:
- Queue contract stays (event, data) — legacy consumers unbroken.
- Frontend accumulators stay alive on _wireSSE — legacy reconnect unbroken.
- Live SSE emits 'id:' so the journal cursor advances correctly.

6 regression tests added in test_stage364_opus_live_sse_event_id.py.
1 existing test (test_run_journal_streaming_static.test_streaming_journals_sse_events_before_queue_delivery) updated to be tuple-shape-agnostic.

Test results:
- Full pytest: 5713 passed, 10 skipped, 1 xfailed, 2 xpassed, 0 failed
- Previously-failing 5 tests: ALL PASS
- 6 new regression tests: ALL PASS
2026-05-16 03:58:54 +00:00
Hermes Agent f3b0c2cb5f stage-364: Opus-caught replay double-render fix + regression test
Opus advisor caught that the new run-journal replay path could double-render
when the live stream errors mid-stream:

- Live SSE frames emitted by _sse() in api/streaming.py:2296 carry no 'id:'
  field. Only _sse_with_id() (used in _replay_run_journal at routes.py:5853)
  emits IDs.
- During live streaming, EventSource.lastEventId stays empty, so the frontend's
  _lastRunJournalSeq stays at 0.
- If the server dies mid-stream, the error reconnect handler opens replay with
  after_seq=0 — server replays every journaled event from seq 1.
- assistantText accumulator (closure scope in messages.js) carries over from
  the live phase. The token handler unconditionally appends d.text. Double-
  rendered text.

Fix: reset assistantText, reasoningText, liveReasoningText, segmentStart, and
set _smdReconnect=true before opening the replay EventSource. Next live token
clears assistantBody.innerHTML to match the reset accumulator.

4 regression tests added in test_stage364_opus_replay_doublerender_fix.py.
Revert-fix verification confirms 3/4 tests fail against reverted code.

This is the TWO-LAYER catch in action: agent self-verified the producer→
consumer chain works end-to-end (Step 3 in agent-side-empirical-verification.md
PASSED for #2283), and Opus independently caught a separate frontend coupling
issue. Both checks required and both fire.
2026-05-16 03:28:07 +00:00
Hermes Agent c0662a4624 Stage 364: PR #2283 — Add WebUI run event journal replay by @franksong2702 2026-05-16 03:08:35 +00:00
Frank Song a3eace4380 Preserve SSE handler test shape 2026-05-16 02:58:34 +00:00
Frank Song 80d8d4b42c Address run journal replay review 2026-05-16 02:58:34 +00:00
Frank Song 3b96035af0 Add WebUI run event journal replay 2026-05-16 02:58:34 +00:00
Michael Lam b373f090bd feat: clarify profiles and workspaces 2026-05-16 02:58:33 +00:00
Hermes Agent 8399a1ade4 Stage 363: PR #2339 — feat: add workspace panel edge reopen toggle by @Michaelyklam 2026-05-16 02:39:23 +00:00
Frank Song 2162dab4a5 Fix pending user row on active reattach 2026-05-16 10:34:55 +08:00
Michael Lam 4d613e723f feat: add workspace panel edge reopen toggle 2026-05-15 18:33:27 -07:00
Hermes Agent 1e6ce3d2e7 Merge pull request #2328 into stage-362
fix: clean session attachment and stream recovery leftovers (Michaelyklam, closes #2325)
2026-05-15 22:55:37 +00:00
Hermes Agent 59f73ba45a Merge pull request #2332 into stage-362
feat: show cron output usage metadata (Michaelyklam)
2026-05-15 22:55:36 +00:00
Hermes Agent 62e4d9b2f5 Merge pull request #2327 into stage-362
fix: use assistant name in cancel copy (dotBeeps)
2026-05-15 22:55:35 +00:00