prompting: end an open tool line before writing a prompt

This commit is contained in:
2026-10-06 19:06:22 +08:00
parent a81b138bf8
commit 1068ea0025
5 changed files with 81 additions and 3 deletions
+3
View File
@@ -7,6 +7,7 @@ import sys
from dataclasses import dataclass
from typing import TYPE_CHECKING, Literal
from plyngent.cli.display import close_open_pretty_line
from plyngent.cli.interrupt import off_loop_prompt, pause_task_cancel_for_prompt
from plyngent.prompting import (
ChoiceOption,
@@ -18,6 +19,7 @@ from plyngent.prompting import (
configure_prompting,
confirm,
get_prompt_backend,
set_prompt_output_hook,
)
from plyngent.tools.access import AccessDecision
from plyngent.tools.process.pty_session import PtyManager
@@ -580,4 +582,5 @@ def install_cli_limit_hooks() -> None:
process-global hook).
"""
configure_prompting(pause_factory=off_loop_prompt)
set_prompt_output_hook(close_open_pretty_line)
PtyManager.set_limit_continue_hook(prompt_continue_limit)
+29 -2
View File
@@ -93,6 +93,30 @@ class PromptBackend(Protocol):
def secho(self, message: str, *, fg: str | None = None, err: bool = False) -> None: ...
# Hook run right before a backend writes prompt chrome (a confirm box, a question
# label). Hosts install one so an open pretty tool line — see
# ``plyngent.cli.display`` — is ended before the prompt takes that line over.
_before_output: Callable[[], None] | None = None
def set_prompt_output_hook(hook: Callable[[], None] | None) -> None:
"""Install the hook run before prompt output (None clears it)."""
global _before_output # noqa: PLW0603
_before_output = hook
def get_prompt_output_hook() -> Callable[[], None] | None:
"""The installed prompt-output hook, if any."""
return _before_output
def _break_output() -> None:
"""Run the prompt-output hook, if one is installed."""
hook = _before_output
if hook is not None:
hook()
def _readline_input(prompt: str, *, completions: Sequence[str] | None = None) -> str:
"""``input()`` with optional Tab completion via readline when available."""
try:
@@ -255,9 +279,11 @@ class ClickPromptBackend:
raise NonInteractiveError(msg) from exc
def echo(self, message: str = "", *, err: bool = False) -> None:
_break_output()
click.echo(message, err=err)
def secho(self, message: str, *, fg: str | None = None, err: bool = False) -> None:
_break_output()
click.secho(message, fg=fg, err=err)
@@ -319,10 +345,11 @@ def get_prompt_backend() -> PromptBackend:
def reset_prompting() -> None:
"""Restore default Click backend, clear the pause hook and cancel flag (tests)."""
global _backend, _pause_factory # noqa: PLW0603
"""Restore the default backend; clear the pause/output hooks and cancel flag (tests)."""
global _backend, _pause_factory, _before_output # noqa: PLW0603
_backend = ClickPromptBackend()
_pause_factory = None
_before_output = None
_prompt_cancel.clear()