Skip to content

fix(android): show interrupt reason instead of bare Response/Run interrupted - #634

Open
ophirhan wants to merge 2 commits into
Codename-11:devfrom
ophirhan:fix/interrupt-reason-display
Open

ophirhan wants to merge 2 commits into
Codename-11:devfrom
ophirhan:fix/interrupt-reason-display

Conversation

@ophirhan

@ophirhan ophirhan commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

When a Gateway/API turn is cancelled, Android Chat often showed a bare Response interrupted or Run interrupted label even if the host already sent a reason (content, error, interrupt_reason, or turn_exit_reason). This PR prefers any non-placeholder server text for the user-visible error path.

Related (hermes-agent — server delivery of interrupt reasons):

Full end-to-end “always an explanation” still depends on the host emitting a reason (agent fix above or equivalent). This client change is defensive: when a reason is present it is shown; when absent, existing bare fallbacks remain.

Changes

  • Add SessionEventPayload.resolveInterruptMessage() (and bare-placeholder detection) prioritizing interrupt_reason / error / content fields, then a humanized turn_exit_reason.
  • Wire resolve helpers through Gateway SSE (GatewayEventMapper, ChatHandler) and API run streams (HermesApiClient).
  • Unit coverage in InterruptReasonResolveTest.
  • CHANGELOG Unreleased note for the user-visible Android behavior.

Verification

  • ./gradlew :app:testSideloadDebugUnitTest --tests com.hermesandroid.relay.network.upstream.models.InterruptReasonResolveTest — BUILD SUCCESSFUL (focused class green; full sideload unit test task also completed successfully on this branch).
  • Android lint: not re-run for this PR cut (rationale: small mapping-only change + focused unit tests).
  • On-device UI dogfood: pass (OnePlus CPH2653, sideload Hermes Relay, 2026-09-27 ~07:12 IDT). Forced Stop mid-turn; chat showed reasoned interrupt text (not bare Response/Run interrupted).

Screenshots

Device proof (OnePlus CPH2653 / Hermes Relay sideload). Cancelled turn shows:

Operation interrupted: explicit stop requested.

Plus the standard recovery banner (“Hermes couldn’t complete this response” with Details / Retry / Dismiss). No layout redesign — copy only.

(Image attached in the following PR comment.)

Compatibility / risk

  • Standard Hermes / unmodified upstream hosts: safe. Missing reason fields keep prior “Response interrupted” / “Run interrupted” fallbacks.
  • No migrations, no plugin/server changes in this PR.
  • Rollout/rollback: client-only; revert commit restores previous labels.
  • Does not claim CLI/gateway interrupt delivery is fixed; that remains on hermes-agent (#84207 / #84236).

Lineage / contributor credit

  • Source PR(s): N/A
  • Attribution preserved by: N/A

Checklist

  • Target branch is dev, unless this is a dev → main release PR or a focused production-tag hotfix PR to main
  • Scope is focused and related issues/PRs are linked
  • Android changes: lint and focused tests ran, or rationale is listed above
  • Translation changes: locale validation/review ran, or N/A is listed above
  • Server/plugin changes: focused tests ran, or N/A/rationale is listed above
  • Desktop changes: build/tests ran, or N/A/rationale is listed above
  • Docs/site changes: build or link/route checks ran, or N/A/rationale is listed above
  • UI changes were tested on a relevant device/emulator/desktop surface, or the missing proof is stated above
  • Commit messages follow Conventional Commits
  • CHANGELOG.md is updated for user-visible changes, or N/A is listed above
  • Public writing hygiene checked: no secrets, private infrastructure, personal names, or AI/process narration
  • Salvaged/replacement work links source PRs and preserves contributor authorship, or N/A is listed above

@hermes-relay-triage hermes-relay-triage Bot added area:android Kotlin app needs-maintainer-review Automated triage exhausted; needs a human labels Sep 27, 2026
@hermes-relay-triage

Copy link
Copy Markdown

🤖 Hermes-Relay automated PR intake

Thanks for opening this focused Android interrupt-reason display fix!

Intake evidence looks solid: the PR targets dev, all template sections are filled, related hermes-agent issue/PR links are present, lineage is marked N/A, and the checklist is checked. Verification lists an exact focused unit-test command with BUILD SUCCESSFUL, and it explicitly notes Android lint was not re-run plus on-device UI proof of a cancelled turn is still outstanding. Screenshots correctly say this is copy-only, with device proof outstanding. Compatibility notes the client-only fallback and that host interrupt delivery is out of scope. CI is still in progress on Android lint, build, test, and the vanilla-upstream route contract; that state is informational only and not a review of correctness.

Nothing else is missing for intake. The outstanding device proof is already stated, so no extra checklist item is needed before review.

A maintainer will review the mapping change and decide whether the stated missing on-device proof should be collected before merge.

@ophirhan

Copy link
Copy Markdown
Contributor Author

Device proof (on-device)

  • Device: OnePlus CPH2653 (sideload Hermes Relay)
  • Time: 2026-09-27 ~07:12 IDT
  • Method: forced Stop mid-turn (not a spontaneous ops failure)
  • Exact interrupt line shown in chat:

Operation interrupted: explicit stop requested.

interrupt reason proof

This is not a bare Response interrupted / Run interrupted / Operation interrupted. placeholder.

ophirhan and others added 2 commits October 18, 2026 07:39
…rrupted

Map server content/error/turn_exit_reason into the chat error path so
Hermes Relay never replaces a cancelled turn with a reasonless label.
@ophirhan
ophirhan force-pushed the fix/interrupt-reason-display branch from 4b38854 to 70f8d47 Compare October 18, 2026 04:39
@ophirhan

Copy link
Copy Markdown
Contributor Author

Rebased onto current dev (force-with-lease). Hygiene-scan clean.

Interrupt-reason display (no bare Response/Run interrupted) is still independent of the quiet-turn ownership work. Android + contract checks re-running.

Ready for review when CI is green.

ophirhan pushed a commit to ophirhan/hermes-agent that referenced this pull request Oct 18, 2026
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

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:android Kotlin app needs-maintainer-review Automated triage exhausted; needs a human

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant