core/tools/process: split write_pty (literal) vs write_pty_keys

This commit is contained in:
2026-07-18 15:46:11 +08:00
parent 4ff03d8135
commit 29230af911
7 changed files with 79 additions and 26 deletions
+1
View File
@@ -21,6 +21,7 @@ from .process import open_pty as open_pty
from .process import read_pty as read_pty
from .process import run_command as run_command
from .process import write_pty as write_pty
from .process import write_pty_keys as write_pty_keys
from .todo import TODO_TOOLS as TODO_TOOLS
from .todo import get_todo_stack as get_todo_stack
from .todo import set_todo_stack as set_todo_stack
+2 -1
View File
@@ -6,5 +6,6 @@ from .pty_terminal import sanitize_pty_output_for_tool as sanitize_pty_output_fo
from .read_pty import read_pty as read_pty
from .run_command import run_command as run_command
from .write_pty import write_pty as write_pty
from .write_pty_keys import write_pty_keys as write_pty_keys
PROCESS_TOOLS = [run_command, open_pty, read_pty, write_pty, close_pty]
PROCESS_TOOLS = [run_command, open_pty, read_pty, write_pty, write_pty_keys, close_pty]
+19 -17
View File
@@ -4,25 +4,12 @@ from plyngent.agent import tool
from plyngent.tools.workspace import WorkspaceError
from .pty_session import PtyManager
from .pty_terminal import decode_write_data
@tool
def write_pty(session_id: int, data: str) -> str:
"""Write text to a PTY session (interactive input). Does not append a newline.
Escapes (literal backslash sequences in ``data``): ``\\n`` ``\\r`` ``\\t``
``\\e``/``\\E`` (ESC), ``\\xHH``, ``\\uHHHH``, ``ctrl+x`` / ``ctrl+c``, and
``key=esc|enter|tab|up|down|left|right``.
"""
try:
raw = decode_write_data(data)
PtyManager.write(session_id, raw)
session = PtyManager.refresh(session_id)
except WorkspaceError as exc:
return f"error: {exc}"
except OSError as exc:
return f"error: failed to write PTY: {exc}"
def write_pty_payload(session_id: int, raw: str) -> str:
"""Write raw bytes (as str) to the PTY and format the tool status string."""
PtyManager.write(session_id, raw)
session = PtyManager.refresh(session_id)
exit_disp = "" if session.exit_code is None else str(session.exit_code)
return "\n".join(
[
@@ -32,3 +19,18 @@ def write_pty(session_id: int, data: str) -> str:
f"wrote={len(raw.encode())}",
]
)
@tool
def write_pty(session_id: int, data: str) -> str:
"""Write **literal** text to a PTY session. Does not append a newline.
``data`` is sent unchanged (no ``ctrl+x`` / ``\\\\xHH`` expansion). For
control sequences use :func:`write_pty_keys`.
"""
try:
return write_pty_payload(session_id, data)
except WorkspaceError as exc:
return f"error: {exc}"
except OSError as exc:
return f"error: failed to write PTY: {exc}"
@@ -0,0 +1,30 @@
from __future__ import annotations
from plyngent.agent import tool
from plyngent.tools.workspace import WorkspaceError
from .pty_terminal import decode_write_data
from .write_pty import write_pty_payload
@tool
def write_pty_keys(session_id: int, data: str) -> str:
"""Write to a PTY after expanding key escapes (never for normal typing).
Use this only for control sequences. Prefer :func:`write_pty` for plain text
so strings like ``press ctrl+c`` are not rewritten.
Escapes (literal characters in ``data``):
- ``\\\\n`` ``\\\\r`` ``\\\\t`` ``\\\\e``/``\\\\E`` (ESC) ``\\\\0``
- ``\\\\xHH`` byte, ``\\\\uHHHH`` Unicode code point
- ``ctrl+c`` / ``ctrl+x`` ... (case-insensitive)
- ``key=esc|enter|tab|up|down|left|right``
"""
try:
raw = decode_write_data(data)
return write_pty_payload(session_id, raw)
except WorkspaceError as exc:
return f"error: {exc}"
except OSError as exc:
return f"error: failed to write PTY: {exc}"