fix(interrupt): preserve pre-start terminal interrupts

This commit is contained in:
helix4u
2026-04-14 23:51:55 -06:00
committed by Teknium
parent a418ddbd8b
commit 93f6f66872
2 changed files with 60 additions and 8 deletions

View File

@@ -28,7 +28,8 @@ class TestInterruptPropagationToChild(unittest.TestCase):
agent = AIAgent.__new__(AIAgent)
agent._interrupt_requested = False
agent._interrupt_message = None
agent._execution_thread_id = None # defaults to current thread in set_interrupt
agent._execution_thread_id = None
agent._interrupt_thread_signal_pending = False
agent._active_children = []
agent._active_children_lock = threading.Lock()
agent.quiet_mode = True
@@ -46,15 +47,17 @@ class TestInterruptPropagationToChild(unittest.TestCase):
assert parent._interrupt_requested is True
assert child._interrupt_requested is True
assert child._interrupt_message == "new user message"
assert is_interrupted() is True
assert is_interrupted() is False
assert parent._interrupt_thread_signal_pending is True
def test_child_clear_interrupt_at_start_clears_thread(self):
"""child.clear_interrupt() at start of run_conversation clears the
per-thread interrupt flag for the current thread.
bound execution thread's interrupt flag.
"""
child = self._make_bare_agent()
child._interrupt_requested = True
child._interrupt_message = "msg"
child._execution_thread_id = threading.current_thread().ident
# Interrupt for current thread is set
set_interrupt(True)
@@ -128,6 +131,36 @@ class TestInterruptPropagationToChild(unittest.TestCase):
child_thread.join(timeout=1)
set_interrupt(False)
def test_prestart_interrupt_binds_to_execution_thread(self):
"""An interrupt that arrives before startup should bind to the agent thread."""
agent = self._make_bare_agent()
barrier = threading.Barrier(2)
result = {}
agent.interrupt("stop before start")
assert agent._interrupt_requested is True
assert agent._interrupt_thread_signal_pending is True
assert is_interrupted() is False
def run_thread():
from tools.interrupt import set_interrupt as _set_interrupt_for_test
agent._execution_thread_id = threading.current_thread().ident
_set_interrupt_for_test(False, agent._execution_thread_id)
if agent._interrupt_requested:
_set_interrupt_for_test(True, agent._execution_thread_id)
agent._interrupt_thread_signal_pending = False
barrier.wait(timeout=5)
result["thread_interrupted"] = is_interrupted()
t = threading.Thread(target=run_thread)
t.start()
barrier.wait(timeout=5)
t.join(timeout=2)
assert result["thread_interrupted"] is True
assert agent._interrupt_thread_signal_pending is False
class TestPerThreadInterruptIsolation(unittest.TestCase):
"""Verify that interrupting one agent does NOT affect another agent's thread.