"""사용자 입력을 세션 내 대화 영역에 표시하는 Textual 애플리케이션.""" from textual.app import App, ComposeResult from textual.containers import VerticalScroll from textual.widgets import Header, Input, Label class ChatApp(App[None]): """LLM 호출 없이 사용자의 제출 입력만 표시하는 초기 TUI.""" CSS = """ Screen { layout: vertical; } #conversation { height: 1fr; border: round $accent; padding: 1; } #user-input { margin: 1 0; } """ BINDINGS = [ ("ctrl+q", "quit", "종료"), ("escape", "quit", "종료"), ] def __init__(self) -> None: super().__init__() self.submitted_inputs: list[str] = [] def compose(self) -> ComposeResult: yield Header(show_clock=False) yield VerticalScroll(id="conversation") yield Input( placeholder="메시지를 입력하고 Enter를 누르세요.", id="user-input", ) def on_mount(self) -> None: self.query_one("#user-input", Input).focus() def on_input_submitted(self, event: Input.Submitted) -> None: """제출된 입력을 기록하고 대화 영역에 누적 표시한다.""" value = event.value if not value: return self.submitted_inputs.append(value) conversation = self.query_one("#conversation", VerticalScroll) conversation.mount(Label(value, classes="user-message")) event.input.value = "" conversation.scroll_end(animate=False) def main() -> None: """콘솔 스크립트의 실행 진입점.""" ChatApp().run() if __name__ == "__main__": main()