Skip to content

Support Queue and Steer while a response is running #23

Description

@nesquena-hermes

Request

When a response is already running, Hermex Android should let the user type another message and choose whether to:

  • Queue it for the next turn, or
  • Steer the active run without stopping it.

Today the only available action during a stream is Stop.

Investigation

This is a confirmed Android-client parity gap, not a WebUI Bridge API limitation.

At current Android master (60b056f6de69a14527caba26312f9ac4601c889c):

No existing Android issue or PR covers Queue/Steer. Android #10 is adjacent but distinct: it fixed Stop followed by edit/resend racing cancellation and producing an active-stream 409.

Available server contract

Steer

Current WebUI supports authenticated POST /api/chat/steer:

{"session_id":"...","text":"..."}

The response is HTTP 200 with:

{"accepted":true|false,"fallback":null|"<reason>","stream_id":"..."|null}

Steer is real mid-run guidance: it calls agent.steer(text) without interrupting the active response. A rejected/unavailable Steer must preserve the draft and must not silently Queue, Stop, or start a normal turn. Relevant fallback reasons include no_cached_agent, agent_lacks_steer, session_not_found, not_running, stream_dead, and steer_error; gateway-owned runs can return the gateway-specific queued fallback.

Queue

Current WebUI master has no public /api/chat/queue endpoint. Browser Queue is a client-owned, session-keyed FIFO that later drains through /api/chat/start, so Android can implement Queue now with local persisted state keyed by both server and session.

Open WebUI PR #6761 proposes a server-authoritative /api/chat/queue, but it is not a stable Bridge contract yet. If it lands, Android should prefer that contract while retaining a capability/version fallback for older servers.

Android also needs to decode pending_steer_leftover: if a steer was accepted but the run finished before reaching a tool-result boundary, WebUI emits this SSE event so the text becomes the next queued normal turn instead of disappearing.

Shared product semantics are tracked in nesquena/hermes-webui#3058.

Expected behavior

  • Keep the composer editable while a response is streaming.
  • Keep Stop available while adding explicit Queue and Steer actions.
  • Queue remains visibly pending and scoped to its originating server/session until it drains, is edited/deleted, or is upgraded to Steer.
  • Steer calls /api/chat/steer, shows an accepted/delivered state, and does not create a duplicate normal user turn.
  • A rejected Steer keeps the user's text and explains the fallback.
  • A pending_steer_leftover event converts the leftover text into a visible queued next turn for the owning session.

Acceptance criteria

  • The user can type while isStreaming == true, with Queue/Steer/Stop all discoverable.
  • Add ChatSteerRequest / ChatSteerResponse DTOs and an authenticated HermexApi.chatSteer() call using the existing server cookie/client.
  • Successful Steer clears only the captured owning draft and is never rendered as a normal queued/user turn.
  • Every HTTP/network/accepted:false Steer path restores or retains the draft for its owning session and leaves the active run untouched.
  • Queue uses a stable FIFO keyed by server ID and session ID, survives navigation, and drains one item only after the active stream settles and the server releases active_stream_id.
  • Queue entries retain normal message context needed by /api/chat/start (text, attachments, model/provider/profile selection, stable ID, and creation time).
  • pending_steer_leftover is decoded and queued once without duplicate drain.
  • Stop keeps its current cancel behavior; immediate Stop/Queue/Steer transitions do not regress the Stop mid-stream then edit + resend → 409 'session already has an active stream', resent message never appears #10 cancellation ordering fix.
  • Tests cover active-run composer state, per-server/session isolation, persistence and drain ordering, no duplicate drain, Steer success and every fallback, session switching, leftover conversion, attachment ownership, auth propagation, and Stop/cancel races.

A text-only Steer first slice is acceptable because the endpoint itself accepts text. Queue should retain normal attachment metadata for its later /api/chat/start; full Steer attachment parity can follow by reusing the existing upload + attached-files marker flow.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions