You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ChatComposer applies that disabled state to the text field and replaces Send with Stop.
ChatViewModel.sendMessage() returns immediately while streaming, so there is no non-UI route for a pending message.
HermexApi exposes chat start and cancel, but not steer.
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:
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.
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.
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.
Request
When a response is already running, Hermex Android should let the user type another message and choose whether to:
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):ChatViewModelexplicitly records steer-while-running as unimplemented. Its comment predates the now-available server contract.ChatComposerState.isTextFieldEnabledbecomes false wheneverisStreamingis true, and the trailing action becomesSTOP.ChatComposerapplies that disabled state to the text field and replaces Send with Stop.ChatViewModel.sendMessage()returns immediately while streaming, so there is no non-UI route for a pending message.HermexApiexposes chat start and cancel, but not steer.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 includeno_cached_agent,agent_lacks_steer,session_not_found,not_running,stream_dead, andsteer_error; gateway-owned runs can return the gateway-specific queued fallback.Queue
Current WebUI
masterhas no public/api/chat/queueendpoint. 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
/api/chat/steer, shows an accepted/delivered state, and does not create a duplicate normal user turn.pending_steer_leftoverevent converts the leftover text into a visible queued next turn for the owning session.Acceptance criteria
isStreaming == true, with Queue/Steer/Stop all discoverable.ChatSteerRequest/ChatSteerResponseDTOs and an authenticatedHermexApi.chatSteer()call using the existing server cookie/client.accepted:falseSteer path restores or retains the draft for its owning session and leaves the active run untouched.active_stream_id./api/chat/start(text, attachments, model/provider/profile selection, stable ID, and creation time).pending_steer_leftoveris decoded and queued once without duplicate drain.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.