mirror of
https://github.com/NCBM/plyngent.git
synced 2026-11-07 15:37:55 +08:00
prompting: let Ctrl+C cancel poll-based prompt reads
The wait tool's prompt runs off-loop on a worker thread, but its read polls select/msvcrt, so it can act on a cancel: the SIGINT target now sets a flag the reader checks between polls and raises PromptCancelledError with, which the tool reports as "cancelled by user" while the turn continues. run_prompt_async / run_cancellable_prompt_async hand the matching hook to the CLI guard; a stale cancel never leaks into the next prompt read.
This commit is contained in:
@@ -3,8 +3,10 @@ from __future__ import annotations
|
||||
import importlib
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from plyngent.agent import ToolRegistry
|
||||
from plyngent.prompting import NonInteractiveBackend, temporary_backend
|
||||
from plyngent.prompting import NonInteractiveBackend, PromptCancelledError, temporary_backend
|
||||
from plyngent.tools.chat import CHAT_TOOLS, ask_user, choose_user, form_user, wait
|
||||
from tests.test_prompting import ScriptedBackend
|
||||
|
||||
@@ -146,6 +148,20 @@ async def test_wait_tool_times_out(monkeypatch) -> None:
|
||||
assert out == "waited 3s"
|
||||
|
||||
|
||||
async def test_wait_tool_cancelled_by_user(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""Ctrl+C during the wait prompt cancels the wait; the turn continues."""
|
||||
|
||||
def _cancelled(prompt: str, timeout: float) -> str:
|
||||
del prompt, timeout
|
||||
raise PromptCancelledError
|
||||
|
||||
monkeypatch.setattr(wait_module, "read_line_with_timeout", _cancelled)
|
||||
with temporary_backend(ScriptedBackend([])):
|
||||
registry = ToolRegistry([wait])
|
||||
out = await registry.execute("wait", '{"duration": 30}')
|
||||
assert out == "cancelled by user"
|
||||
|
||||
|
||||
async def test_wait_tool_prompt_two_lines_with_reason(monkeypatch) -> None:
|
||||
prompts: list[str] = []
|
||||
monkeypatch.setattr(
|
||||
|
||||
Reference in New Issue
Block a user