Add contributor guide and project usage docs

This commit is contained in:
2026-02-16 22:48:05 +09:00
parent 1e552f8c46
commit 87482efd6d
16 changed files with 671 additions and 1 deletions

View File

@@ -0,0 +1,56 @@
"""pexpect 기반 PTY 프로세스 관리."""
from __future__ import annotations
import logging
import pexpect
logger = logging.getLogger(__name__)
class PtyManager:
"""가상 터미널에서 CLI 프로세스를 생성하고 입출력을 제어한다."""
def __init__(self, command: str = "claude") -> None:
self.command = command
self._process: pexpect.spawn | None = None
@property
def is_alive(self) -> bool:
return self._process is not None and self._process.isalive()
def start(self) -> None:
"""프로세스를 시작한다."""
logger.info("프로세스 시작: %s", self.command)
self._process = pexpect.spawn(
self.command,
encoding="utf-8",
timeout=None,
)
def send(self, text: str) -> None:
"""프로세스에 텍스트 입력을 전달한다."""
if not self.is_alive:
raise RuntimeError("프로세스가 실행 중이 아닙니다.")
assert self._process is not None
logger.debug("입력 전송: %s", text)
self._process.sendline(text)
def read_output(self, timeout: int = 5) -> str:
"""프로세스의 출력을 읽는다."""
if not self.is_alive:
raise RuntimeError("프로세스가 실행 중이 아닙니다.")
assert self._process is not None
try:
self._process.expect(pexpect.TIMEOUT, timeout=timeout)
except pexpect.TIMEOUT:
pass
return self._process.before or ""
def stop(self) -> None:
"""프로세스를 종료한다."""
if self._process is not None:
logger.info("프로세스 종료")
self._process.close(force=True)
self._process = None