From b57134bf2bb160768594f9bbb905c1ff349ed2a0 Mon Sep 17 00:00:00 2001 From: starship-s <45587122+starship-s@users.noreply.github.com> Date: Mon, 27 Apr 2026 23:48:15 -0600 Subject: [PATCH] ui: reflect explicit busy slash command in send button --- static/ui.js | 21 +++++++++++++++++++++ tests/test_1062_busy_input_modes.py | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/static/ui.js b/static/ui.js index 54114847..f659c257 100644 --- a/static/ui.js +++ b/static/ui.js @@ -1194,6 +1194,25 @@ function _composerHasContent(){ return !!((msg&&msg.value.trim().length>0)||S.pendingFiles.length>0); } +function _getExplicitBusyCommandAction(text){ + const trimmed=(text||'').trim(); + if(!trimmed.startsWith('/')) return null; + const body=trimmed.slice(1); + const name=(body.split(/\s+/)[0]||'').toLowerCase(); + const args=body.slice(name.length).trim(); + if(!args) return null; + if(name==='queue') return 'queue'; + if(name==='steer'){ + if(S.activeStreamId&&typeof _trySteer==='function') return 'steer'; + return 'queue'; + } + if(name==='interrupt'){ + if(S.activeStreamId&&typeof cancelStream==='function') return 'interrupt'; + return 'queue'; + } + return null; +} + function getComposerPrimaryAction(){ const msg=$('msg'); const hasContent=_composerHasContent(); @@ -1206,6 +1225,8 @@ function getComposerPrimaryAction(){ if(S.activeStreamId&&typeof cancelStream==='function') return 'stop'; return 'disabled'; } + const explicitAction=_getExplicitBusyCommandAction(msg&&msg.value); + if(explicitAction) return explicitAction; const busyMode=window._busyInputMode||'queue'; if(busyMode==='steer'){ if(S.activeStreamId&&typeof _trySteer==='function') return 'steer'; diff --git a/tests/test_1062_busy_input_modes.py b/tests/test_1062_busy_input_modes.py index e2d3c21c..7e70ca5b 100644 --- a/tests/test_1062_busy_input_modes.py +++ b/tests/test_1062_busy_input_modes.py @@ -178,6 +178,26 @@ class TestBusySendButton: assert "return 'interrupt'" in body, "interrupt mode with an active stream must map to interrupt" assert "return 'steer'" in body, "steer mode with active stream support must map to steer" assert "window._busyInputMode||'queue'" in body, "helper must respect the Busy input mode setting" + assert "_getExplicitBusyCommandAction(msg&&msg.value)" in body, ( + "explicit /queue, /interrupt, and /steer drafts must override the Busy input mode for button visuals" + ) + + def test_explicit_busy_commands_override_button_visual_action(self): + idx = UI_JS.find("function _getExplicitBusyCommandAction(") + assert idx >= 0, "_getExplicitBusyCommandAction() not found" + body = UI_JS[idx:UI_JS.find("function getComposerPrimaryAction", idx)] + assert "name==='queue'" in body and "return 'queue'" in body, ( + "typing /queue should show the queue/list-end button even in another busy mode" + ) + assert "name==='steer'" in body and "return 'steer'" in body, ( + "typing /steer should show the steer/compass button even when the global mode is queue" + ) + assert "name==='interrupt'" in body and "return 'interrupt'" in body, ( + "typing /interrupt should show the interrupt/skip-forward button even in another busy mode" + ) + assert "if(!args) return null" in body, ( + "partial slash commands without a payload should not override the primary button while the user is still typing" + ) def test_send_button_click_uses_primary_action_handler(self): assert "function handleComposerPrimaryAction()" in UI_JS, (