Merge #4127 (run /yolo immediately on busy send path) onto master
This commit is contained in:
commit
45b88b55b7
4 changed files with 46 additions and 8 deletions
|
|
@ -910,13 +910,14 @@ async function send(){
|
|||
if(!S.session){await newSession();await renderSessionList();}
|
||||
// Busy-control slash commands must be intercepted HERE, before the
|
||||
// busyMode routing block, so the user can always type /steer, /interrupt,
|
||||
// or /queue while the agent is running and have them execute immediately.
|
||||
// /queue, /terminal, /goal, or /yolo while the agent is running and have
|
||||
// them execute immediately.
|
||||
// Without this intercept they fall through to the queue and execute after
|
||||
// the current turn ends — by which point there is no active stream and
|
||||
// cmdSteer / cmdInterrupt say "No active task to stop."
|
||||
if(text.startsWith('/')){
|
||||
const _pc=typeof parseCommand==='function'&&parseCommand(text);
|
||||
if(_pc&&['steer','interrupt','queue','terminal','goal'].includes(_pc.name)){
|
||||
if(_pc&&['steer','interrupt','queue','terminal','goal','yolo'].includes(_pc.name)){
|
||||
const _bc=COMMANDS.find(c=>c.name===_pc.name);
|
||||
if(_bc){
|
||||
$('msg').value='';autoResize();
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ class TestSendBusyBranchDispatch:
|
|||
|
||||
|
||||
def test_slash_commands_intercepted_before_busymode_routing(self):
|
||||
"""The three busy-control slash commands (/steer /interrupt /queue) must be
|
||||
"""Busy-control slash commands (/steer /interrupt /queue /yolo) must be
|
||||
intercepted at the TOP of the busy block — before the busyMode routing — so
|
||||
they execute immediately while the agent is running.
|
||||
|
||||
|
|
@ -298,22 +298,26 @@ class TestSendBusyBranchDispatch:
|
|||
busy_start = MESSAGES_JS.find("S.busy||compressionRunning", send_idx)
|
||||
assert busy_start >= 0, "busy block not found"
|
||||
# The intercept must appear BEFORE the busyMode assignment
|
||||
intercept_idx = MESSAGES_JS.find("'steer','interrupt','queue'", busy_start)
|
||||
intercept_idx = MESSAGES_JS.find("'steer','interrupt','queue','terminal','goal','yolo'", busy_start)
|
||||
busymode_idx = MESSAGES_JS.find("_busyInputMode||'queue'", busy_start)
|
||||
assert intercept_idx >= 0, (
|
||||
"send() must intercept /steer /interrupt /queue before the busyMode "
|
||||
"send() must intercept /steer /interrupt /queue /terminal /goal /yolo before the busyMode "
|
||||
"routing block — otherwise they queue instead of executing immediately"
|
||||
)
|
||||
assert intercept_idx < busymode_idx, (
|
||||
"The slash-command intercept must come BEFORE the busyMode routing "
|
||||
"so /steer executes while the agent is running, not after the turn ends"
|
||||
)
|
||||
intercept_block = MESSAGES_JS[intercept_idx:busymode_idx]
|
||||
assert "'yolo'" in intercept_block, (
|
||||
"The busy-mode slash-command allowlist must include /yolo"
|
||||
)
|
||||
|
||||
def test_steer_intercept_calls_handler_directly(self):
|
||||
"""The busy-intercept must dispatch via _bc.fn(_pc.args), not queue the text."""
|
||||
send_idx = MESSAGES_JS.find("async function send(")
|
||||
busy_start = MESSAGES_JS.find("S.busy||compressionRunning", send_idx)
|
||||
intercept_idx = MESSAGES_JS.find("'steer','interrupt','queue'", busy_start)
|
||||
intercept_idx = MESSAGES_JS.find("'steer','interrupt','queue','terminal','goal','yolo'", busy_start)
|
||||
assert intercept_idx >= 0
|
||||
# Get the intercept block (up to the next busyMode assignment)
|
||||
busymode_idx = MESSAGES_JS.find("_busyInputMode||'queue'", busy_start)
|
||||
|
|
@ -335,7 +339,7 @@ class TestSendBusyBranchDispatch:
|
|||
"""
|
||||
send_idx = MESSAGES_JS.find("async function send(")
|
||||
busy_start = MESSAGES_JS.find("S.busy||compressionRunning", send_idx)
|
||||
intercept_idx = MESSAGES_JS.find("'steer','interrupt','queue'", busy_start)
|
||||
intercept_idx = MESSAGES_JS.find("'steer','interrupt','queue','terminal','goal','yolo'", busy_start)
|
||||
busymode_idx = MESSAGES_JS.find("_busyInputMode||'queue'", busy_start)
|
||||
intercept_block = MESSAGES_JS[intercept_idx:busymode_idx]
|
||||
clear_idx = intercept_block.find("$('msg').value=''")
|
||||
|
|
|
|||
|
|
@ -408,7 +408,7 @@ def test_frontend_has_goal_slash_command_and_status_event_handler():
|
|||
assert "goal'" in MESSAGES_JS
|
||||
assert "source.addEventListener('goal'" in MESSAGES_JS
|
||||
assert "source.addEventListener('goal_continue'" in MESSAGES_JS
|
||||
assert "['steer','interrupt','queue','terminal','goal'].includes(_pc.name)" in MESSAGES_JS
|
||||
assert "['steer','interrupt','queue','terminal','goal','yolo'].includes(_pc.name)" in MESSAGES_JS
|
||||
assert "queueSessionMessage" in MESSAGES_JS
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,39 @@ class TestYoloCommandRegistration:
|
|||
assert "/api/session/yolo" in commands_js
|
||||
|
||||
|
||||
class TestYoloBusySendPath:
|
||||
"""/yolo should be recognized by the busy-send command intercept."""
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def messages_js(self):
|
||||
with open("static/messages.js", "r") as f:
|
||||
return f.read()
|
||||
|
||||
def test_yolo_in_busy_send_allowlist(self, messages_js):
|
||||
send_idx = messages_js.find("async function send(")
|
||||
assert send_idx >= 0, "send() not found in messages.js"
|
||||
busy_start = messages_js.find("S.busy||compressionRunning", send_idx)
|
||||
assert busy_start >= 0, "busy block not found in send()"
|
||||
intercept_start = messages_js.find("if(text.startsWith('/')", busy_start)
|
||||
assert intercept_start >= 0, "busy slash intercept block not found in send()"
|
||||
intercept_idx = messages_js.find("'steer','interrupt','queue','terminal','goal','yolo'", intercept_start)
|
||||
busymode_idx = messages_js.find("_busyInputMode||'queue'", busy_start)
|
||||
assert intercept_idx >= 0, "Busy-path slash allowlist must include yolo in the mid-turn branch"
|
||||
assert intercept_idx < busymode_idx, "Busy-path intercept must run before busyMode routing"
|
||||
|
||||
intercept_block = messages_js[intercept_idx:busymode_idx]
|
||||
assert "_bc.fn(_pc.args)" in intercept_block, (
|
||||
"Busy-path slash intercept should dispatch directly through the command handler"
|
||||
)
|
||||
assert "await _bc.fn" in intercept_block, (
|
||||
"Busy-path slash intercept should await the command handler"
|
||||
)
|
||||
clear_idx = intercept_block.find("$('msg').value=''")
|
||||
await_idx = intercept_block.find("await _bc.fn")
|
||||
assert clear_idx >= 0, "Busy-path intercept should clear composer text before await"
|
||||
assert clear_idx < await_idx, "Composer clear must happen before awaiting the handler"
|
||||
|
||||
|
||||
class TestYoloPillHTML:
|
||||
"""YOLO pill element should exist in index.html."""
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue