Skip to content

fix(interrupt): always surface a user-visible stop reason - #138011

Open
ophirhan wants to merge 1 commit into
NousResearch:mainfrom
ophirhan:fix/interrupt-reason-user-visible-main
Open

ophirhan wants to merge 1 commit into
NousResearch:mainfrom
ophirhan:fix/interrupt-reason-user-visible-main

Conversation

@ophirhan

Copy link
Copy Markdown

Summary

Interrupted turns that ended with empty final text (hard stop, tool timeout, client-gone, lease takeover) could settle as a blank chat: no reason line, error_retained=False, and Desktop skipped the no-reply card for interrupted turns.

This PR always produces a user-visible stop reason on empty interrupts and carries it through host → gateway/API/TUI → Desktop.

Changes

  • Agent: format_interrupt_user_text / ensure_interrupt_final_response — never emit bare Operation interrupted.; prefer tool_reason, exit reason, or session-id pointer into agent.log
  • Finalizer: fill reasoned final_response (and error) before persist on interrupted turns
  • TUI gateway: interrupted message.complete always sets error + non-empty text; system lifecycle stops pass distinct tool_reason (not mislabeled user Stop)
  • Gateway chat + API runs: deliver interrupt reason instead of discarding bare cancel
  • Desktop/WebUI: interrupted empty settle paints a non-retryable stop notice; message.complete falls back to error when text is empty

Related

Test plan

  • ./scripts/run_tests.sh tests/agent/test_format_interrupt_user_text.py
  • ./scripts/run_tests.sh tests/agent/test_close_interrupted_tool_sequence.py
  • TUI interrupt suite (test_interrupt_dead_compute_host, hook, background review, does_not_wait)
  • Desktop vitest session-states-interrupted-settle.test.ts (CI)
  • Manual: stop mid-tool / terminal batch timeout → chat shows Operation interrupted: … not blank

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/gateway Gateway runner, session dispatch, delivery comp/tui Terminal UI (ui-tui/ + tui_gateway/) comp/desktop Electron desktop app (apps/desktop/*) sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages area/sessions Session lifecycle, resume, persistence, history labels Oct 13, 2026
@ophirhan

Copy link
Copy Markdown
Author

Rebased onto current main (84f748ce65f).

  • Desktop no-reply helpers now live in session-no-reply.ts on main — moved the interrupted-empty notice there and wired markTurnWithoutReply to paint a non-retryable stop card instead of going blank.
  • Python unit tests: tests/agent/test_format_interrupt_user_text.py 7/7 green.
  • Desktop: session-states-interrupted-settle.test.ts 2/2 green.

Related: #84207 · pairs with Codename-11/hermes-relay#634 (phone display).

@ophirhan
ophirhan force-pushed the fix/interrupt-reason-user-visible-main branch from 2f5f8e1 to 84f748c Compare October 18, 2026 06:41
@alt-glitch alt-glitch added area/streaming Streaming responses: gateway delivery, provider wire desktop/sessions Session management in the desktop app: session list and sidebar, creating, switching, resuming, rena labels Oct 18, 2026
@ophirhan
ophirhan force-pushed the fix/interrupt-reason-user-visible-main branch from 84f748c to a232236 Compare October 18, 2026 07:56
@ophirhan

Copy link
Copy Markdown
Author

Rebased onto current main (a23223660ab). Unique commit is still the interrupt-reason fill only. Ready for review.

Empty interrupted turns (hard stop, timeout, client-gone) no longer settle
as silence or bare "Operation interrupted." Host fills a reasoned final
line; gateway/API/TUI complete payloads carry error+text; Desktop paints a
non-retryable stop notice instead of a blank chat. System lifecycle stops
pass distinct tool_reason so they are not mislabeled as user Stop.

Related: NousResearch#84207, Codename-11/hermes-relay#634
@ophirhan
ophirhan force-pushed the fix/interrupt-reason-user-visible-main branch from a232236 to 1c0941b Compare October 19, 2026 16:56

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history area/streaming Streaming responses: gateway delivery, provider wire comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/desktop Electron desktop app (apps/desktop/*) comp/gateway Gateway runner, session dispatch, delivery comp/tui Terminal UI (ui-tui/ + tui_gateway/) desktop/sessions Session management in the desktop app: session list and sidebar, creating, switching, resuming, rena P2 Medium — degraded but workaround exists sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants