Skip to content

Commit 76414a4

Browse files
committed
cli-6: added interruption fix
1 parent 5873909 commit 76414a4

2 files changed

Lines changed: 34 additions & 8 deletions

File tree

cecli/coders/base_coder.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ def __init__(
328328
uuid="",
329329
):
330330
# initialize from args.map_cache_dir
331+
self.interrupt_event = asyncio.Event()
331332
self.uuid = generate_unique_id()
332333
if uuid:
333334
self.uuid = uuid
@@ -1735,6 +1736,7 @@ def keyboard_interrupt(self):
17351736

17361737
self.io.tool_warning("\n\n^C KeyboardInterrupt")
17371738

1739+
self.interrupt_event.set()
17381740
self.last_keyboard_interrupt = time.time()
17391741

17401742
# Old summarization system removed - using context compaction logic instead
@@ -3039,6 +3041,7 @@ async def check_for_file_mentions(self, content):
30393041
return prompts.added_files.format(fnames=", ".join(added_fnames))
30403042

30413043
async def send(self, messages, model=None, functions=None, tools=None):
3044+
self.interrupt_event.clear()
30423045
self.got_reasoning_content = False
30433046
self.ended_reasoning_content = False
30443047

@@ -3058,15 +3061,33 @@ async def send(self, messages, model=None, functions=None, tools=None):
30583061
self.token_profiler.start()
30593062

30603063
try:
3061-
hash_object, completion = await model.send_completion(
3062-
messages,
3063-
functions,
3064-
self.stream,
3065-
self.temperature,
3066-
# This could include any tools, but for now it is just MCP tools
3067-
tools=tools,
3068-
override_kwargs=self.model_kwargs.copy(),
3064+
completion_task = asyncio.create_task(
3065+
model.send_completion(
3066+
messages,
3067+
functions,
3068+
self.stream,
3069+
self.temperature,
3070+
# This could include any tools, but for now it is just MCP tools
3071+
tools=tools,
3072+
override_kwargs=self.model_kwargs.copy(),
3073+
)
3074+
)
3075+
interrupt_task = asyncio.create_task(self.interrupt_event.wait())
3076+
3077+
done, pending = await asyncio.wait(
3078+
{completion_task, interrupt_task},
3079+
return_when=asyncio.FIRST_COMPLETED,
30693080
)
3081+
3082+
if interrupt_task in done:
3083+
completion_task.cancel()
3084+
try:
3085+
await completion_task
3086+
except asyncio.CancelledError:
3087+
pass
3088+
raise KeyboardInterrupt
3089+
3090+
hash_object, completion = completion_task.result()
30703091
self.chat_completion_call_hashes.append(hash_object.hexdigest())
30713092

30723093
if not isinstance(completion, ModelResponse):

cecli/io.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,11 @@ def rule(self):
758758
print()
759759

760760
def interrupt_input(self):
761+
if self.coder:
762+
coder = self.coder()
763+
if coder and hasattr(coder, "interrupt_event"):
764+
coder.interrupt_event.set()
765+
761766
if self.prompt_session and self.prompt_session.app:
762767
# Store any partial input before interrupting
763768
self.placeholder = self.prompt_session.app.current_buffer.text

0 commit comments

Comments
 (0)