Commit Graph

5 Commits

Author SHA1 Message Date
nesquena-hermes
d39d30a213 fix: correct message ordering after task cancellation — v0.50.163 (#883)
fix: correct message ordering after task cancellation — v0.50.163 (#883)

Fixes the message-ordering glitch from #882: clicking Cancel while the
agent is responding could cause a subsequent response to render above
the "*Task cancelled.*" marker.

Root cause: the cancel handler pushed the marker only to local S.messages
without persisting to the server. When the done event fired shortly after
and replaced S.messages from server state, the marker disappeared from
client state while the next response anchored to the server-authoritative
position.

Fix has three parts:
- Server (cancel_stream): append *Task cancelled.* to session.messages
  with _error:True + timestamp, then save. _error ensures
  _sanitize_messages_for_api() strips it from conversation_history on
  the next agent turn, so the LLM never sees it as a prior assistant
  turn. Precedent: same flag used for the apperror marker at line 1343.
- Client (SSE cancel handler): fetch /api/session instead of pushing
  locally (same pattern as the done handler). Falls back to local push
  if the fetch fails.
- Tests: fix test window width for cancel handler (1200→dynamic); add
  two regression tests pinning _error flag and _sanitize invariant.

1941 tests passing.

Co-authored-by: piliang <piliang1@jd.com>
2026-04-22 22:17:40 -07:00
nesquena-hermes
859602340e fix: streaming race conditions (#631) + blank-page workspace binding (#804)
Closes #631. Closes #804.

Bug A (thinking card below answer / double render / stuck cursor): trailing rAF after 'done'
inserted a duplicate live-turn wrapper into already-settled DOM. Fixed via _streamFinalized flag
+ cancelAnimationFrame in all terminal handlers (done/apperror/cancel/_handleStreamError) +
_scheduleRender guard. All three reported symptoms were the same root cause.

Bug B (accumulator reset): original fix reset assistantText/reasoningText inside _wireSSE on reconnect.
Reverted — server uses one-shot queue.Queue(), no replay on reconnect, reset would wipe valid
pre-drop content causing data loss. Bug A fix alone resolves all symptoms.

#804 (blank page workspace): syncWorkspaceDisplays uses S._profileDefaultWorkspace as fallback;
workspace chip enabled when hasWorkspace (not hasSession); promptNewFile/promptNewFolder/
switchToWorkspace/promptWorkspacePath auto-create session on blank page; boot.js hydrates
_profileDefaultWorkspace from /api/settings before any session exists.

Opus max-effort review + Nathan independent review + full browser QA. 1765/1765 tests.
2026-04-21 18:47:40 -07:00
nesquena-hermes
067d96bb30 feat: add full Russian (ru-RU) localization — v0.50.95 (PR #713)
Full Russian locale — 389/389 English keys, Slavic plural forms, native Cyrillic. Rebased from PR #605 with rebase artifacts fixed. Login page Russian added to api/routes.py. Credits: @DrMaks22 (translation), @renheqiang (PR #605 author).

Co-authored-by: DrMaks22 <DrMaks22@users.noreply.github.com>
Co-authored-by: renheqiang <renheqiang@users.noreply.github.com>
2026-04-19 06:47:24 +00:00
Hermes Agent
1bd0341243 fix: expand test_sprint36 search window for setBusy after stopClarifyPolling additions 2026-04-15 07:24:53 +00:00
nesquena-hermes
bd3ec45aa9 fix: cancel cleanup no longer depends on SSE event (closes #299)
cancelStream() now clears S.activeStreamId, calls setBusy(false),
setStatus(''), and hides the cancel button directly after the cancel
API request completes. Previously cleanup depended on the SSE 'cancel'
event, which never arrived if the connection was already closed —
leaving 'Cancelling...' status and busy spinner stuck indefinitely.

The SSE cancel handler in messages.js still fires when the connection
is alive and performs additional cleanup (adds 'Task cancelled.' message,
clears tool cards). All operations are idempotent.

9 new tests in tests/test_sprint36.py.

Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-12 11:08:59 -07:00