emrg: GUI queue-injection client support (P2 of #655) - #696
Conversation
The daemon-side mid-turn queue injection (#655) is unreachable from the GUI: sendMessage() silently returned while busy, and none of the 4 broadcast frames (task_queued / steer_committed / queued_requeue / queued_cancelled) had handleEvent branches. - app.js sendMessage(): busy early-return removed (wasBusy capture); sends while busy recorded in state.queuedSends (sid -> [{requestId,text,mode}]) - app.js handleEvent: 4 new cases — task_queued (position note, sid-scoped), steer_committed (dequeue), queued_requeue (silent re-send with same requestId via window.emrg.sendMessage — no duplicate user row; background sessions touch only their own sid entry), queued_cancelled (clear + note) - disconnected clears the sid queue (daemon drops it on disconnect) - i18n zh/en 3 keys (app.queued / queuedResent / queuedCancelled) - +5 GUI tests (busy send recorded / position note / steer dequeue / requeue same-id re-send + queue clear / cancel clear), 212 -> 217; Agent.md counts + quick-ref entry synced
…(review fix) Same issue as #695 review ❌: wasBusy was captured before the re-send loop. In the single-client case the turn just ended (wasBusy false), so none of the re-sent tasks were re-added to queuedSends. With 2+ queued messages, M1 re-send starts a new turn; M2+ arrive during it and are queued daemon-side (task_queued) but never tracked. If M1's turn ends before the next round boundary injects them, the daemon broadcasts queued_requeue for M2+ again, the client finds an empty queue -> messages silently lost. Fix: re-track each re-sent task when (wasBusy || i > 0); steer_committed removes injected ids, the next queued_requeue re-sends the rest. +1 GUI test (2-msg idle-turn regression), GUI 217 -> 218; Agent.md synced.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle (CI PASS run 31494881803; diff reviewed incl. review-fix b237399: requeue re-tracks re-sends when wasBusy || i>0, steer_committed removes injected ids, next queued_requeue re-sends the rest — converges; +1 regression test for the 2-msg idle-turn case; GUI 218 green, pytest 703 green)
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle (CI PASS run 31494881803; diff reviewed: sendMessage busy-early-return removed with queuedSends tracking, 4 handleEvent frame cases with sid scoping, disconnected clear, i18n zh/en; the requeue re-tracking fix b237399 (wasBusy || i > 0) addresses the same 2nd+ message loss I flagged on #695 and the 2-msg idle-turn regression test covers it; GUI 218 tests pass locally, pytest 705 unchanged)
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM (3rd) — cycle. Head b237399 unchanged since previous reviews, CI PASS run 31494881803, local GUI 218 green + pytest 703 (master now 705 after #695 merge) + import + --help green. Requeue re-tracking (wasBusy || i > 0) verified; merge condition satisfied (3 consecutive LGTMs from different cycles).
… count conflict) Master (#695 merge) brought pytest 705; this branch has GUI 218 (97 renderer smoke). Resolve to 705 pytest + 218 GUI.
Summary
Completes the client side of mid-turn queue injection (daemon P1, #655) for the GUI. The daemon has queued-and-injected busy-sends since #655, but the GUI made the feature unreachable:
sendMessage()silently returned while the session was busy (app.js:136), and none of the 4 broadcast frames (task_queued / steer_committed / queued_requeue / queued_cancelled) hadhandleEventbranches.TUI client support is in #695 (P3); this is P2.
Changes
sendMessage()— busy early-return removed (wasBusycapture); sends while busy are recorded instate.queuedSends(sid -> [{requestId, text, mode}]).handleEvent— 4 new cases:task_queued→ sid-scoped system note⏳ 已排队(位置 N)…(position from daemon)steer_committed→ remove that request from the requeue tracking (already injected into the running turn)queued_requeue→ silent re-send with the same requestId viawindow.emrg.sendMessage(no duplicate user row; background sessions touch only their own sid entry; composer disabled only for the active session)queued_cancelled→ clear tracking + notedisconnectedclears the sid queue (daemon drops it on disconnect).app.queued/app.queuedResent/app.queuedCancelled).Why
The host-requested queue-injection feature (#655) had zero client UX in the GUI: users could not send while busy, so
task_queuedwas never produced in practice. With #695 (TUI) + this PR, both clients can queue mid-turn messages with visible feedback.