← Phase 1 Phase 1.5 • Day 11 Terminal Cockpit

Local SE Agent Masterclass

MacBook M3 16GB • Complete Implementation Standard
📍 ส่วนที่ 1: หมุดตั้งโจทย์ & วัตถุประสงค์หลัก (Title Connection)

Chapter 11 — Production-Grade Rich CLI & Interactive REPL Shell

ทำไมต้องชื่อนี้และเรียนไปเพื่ออะไร?

ใน Day 1 ถึง Day 10 เราสร้างอวัยวะครบหมดทุกส่วนแล้ว: มีตาอ่านไฟล์ (Day 4), มีเท้าสั่งรันเทส (Day 5), มีสมอง ReAct Loop (Day 6), มีความจำระยะสั้น Sliding Window (Day 8), มีความจำระยะยาว ChromaDB (Day 9), และมีมือแก้โค้ดพร้อม Diff + Rollback (Day 10)

แต่ปัญหาคอขาดบาดตายของการใช้งานจริงคือ: ใน Day 7 เราใช้แค่คำสั่ง print() ดิบๆ บน Terminal ธรรมดา ซึ่งเวลา Agent ใช้เวลาคิด 10-15 วินาที หน้าจอ Terminal จะ **"ค้างนิ่งสนิท ไร้สัญญาณชีพ (Freeze)"** มนุษย์ไม่รู้เลยว่า AI กำลังคิด กำลังรันเทส หรือเครื่อง Mac ค้างไปแล้ว! และผลลัพธ์ที่พิมพ์ออกมาก็เป็นข้อความยาวเหยียด ไม่มีสีสัน ไม่มีตารางสรุป และอ่านโค้ดแทบไม่รู้เรื่อง!

Day 11 เราจึงต้องสร้าง Production-Grade Terminal Cockpit ด้วยไลบรารีระดับอุตสาหกรรม rich โดยยกเครื่องหน้าจอห้องบังคับการใหม่ทั้งหมด:
1. Animated Live Spinners: ตัวหมุนอนิเมชั่นรายงานสถานะ Real-time ขณะ AI กำลังคิดหรือรันคำสั่ง
2. Syntax Highlighting & Markdown Panels: แสดงผลลัพธ์โค้ด กรอบข้อความ และตารางสรุปผลอย่างสวยงาม
3. Graceful REPL Shell with History: โหมดโต้ตอบต่อเนื่องที่รองรับการยกเลิก Ctrl+C อย่างสง่างาม ไม่พ่น Error แดงเถือก!

✓ Day 1-7: Core Engine & CLI ✓ Day 8-10: Memory, ChromaDB & Safe Diff Day 11: Production Rich CLI Cockpit 🖥️✨ Day 12: Safety Guardrails
📂 ส่วนที่ 2: ผังโครงสร้างโปรเจกต์จริง & ตำแหน่งไฟล์ (Project File Structure)

โค้ดประจำ Day 11 จะติดตั้ง rich เพิ่มใน requirements.txt สร้างโมดูลควบคุมหน้าจอแสดงผล core/ui.py และอัปเกรด main.py สู่ห้องบังคับการระดับ Production:

se_agent/
├── requirements.txt                       # [อัปเดต Day 11] เพิ่ม rich>=13.7.0
├── main.py                               # [อัปเกรด Day 11] Production Rich CLI Entrypoint (สวยงามระดับ Copilot)
├── test_rich_ui.py                       # [ไฟล์ใหม่ Day 11] สคริปต์ทดสอบคอมโพเนนต์ UI: Panels, Spinners, Tables, Diff
├── memory/
│   ├── __init__.py
│   ├── context.py                          # Sliding Window Memory (Day 8)
│   └── vector_store.py                     # ChromaDB Vector Store (Day 9)
├── core/
│   ├── __init__.py                         # [อัปเดต Day 11] Export: TerminalUI
│   ├── client.py                          # Ollama Client Wrapper
│   ├── parser.py                          # JSON Parser
│   ├── dispatcher.py                      # Tool Dispatcher
│   ├── engine.py                          # ReAct Agent Engine
│   ├── ui.py                              # [ไฟล์ใหม่ Day 11] TerminalUI Manager: Render Panels, Tables, Live Spinners
│   └── tools/
│       ├── __init__.py
│       ├── file_reader.py                  # Tool 1: File Reader
│       ├── test_runner.py                  # Tool 2: Maven Runner
│       └── code_refactor.py                # Tool 3: Safe Refactor & Diff (Day 10)
└── sample_maven_project/
📍 core/ui.py ทำหน้าที่อะไร?

ทำหน้าที่เป็น Presentation Layer Manager รวบรวมเมธอดการวาด Banner ต้อนรับ, การสร้าง Live Spinner ขณะรอ Ollama หรือ Maven, การเรนเดอร์ Markdown Panels, ตารางสรุปการทำงานของ Tools, และการจัดแสดง Unified Diff ด้วยสีเขียว/แดงอย่างมืออาชีพ

📍 main.py (อัปเกรด) ทำหน้าที่อะไร?

ยกระดับจาก CLI ข้อความดิบ สู่ Interactive Cockpit Shell มีแถบสถานะชัดเจนว่ากำลังรันโมเดลไหน, ใช้หน่วยความจำเท่าไหร่, แสดงข้อคิด (Thought) ในกล่องสีม่วง, แสดง Tool Call ในกล่องสีฟ้า และแสดงผลลัพธ์สุดท้ายในกล่องสีเขียว

🏛️ ส่วนที่ 3: สถาปัตยกรรม Terminal Presentation Layer (Mental Model)
แผนผังการไหลของข้อมูล: Terminal User Interaction ➔ Rich Presentation Layer ➔ ReAct Brain
🧑‍💻
1. Prompt Input
`Prompt.ask()`

รับคำสั่งพร้อมปุ่ม Escape/Quit ดักจับ Ctrl+C นุ่มนวล

🌀
2. Live Status Spinner
`console.status()`

หมุนอนิเมชั่น Real-time แจ้งว่า Agent กำลังทำอะไร ไม่ค้าง

📦
3. Styled Panels
`Panel(Markdown(...))`

แยกกล่อง Thought, Action, และ Observation ชัดเจน

📊
4. Syntax & Table
`Table` & `Syntax`

พรีวิวโค้ดไฮไลต์สี และตารางสรุปผลลัพธ์ระดับ Enterprise

ทำไมการมี Rich Presentation Layer ถึงสร้างความแตกต่างระดับฟ้ากับเหว?
❌ CLI แบบเดิม (Text Dumps):

1. เมื่อสั่งรันเทส 20 วินาที หน้าจอค้างนิ่ง มนุษย์นึกว่าโปรแกรมแฮงก์แล้วเผลอกด Ctrl+C ทำลายงาน
2. ข้อความ Thought ปนกับ Stack Trace อ่านยากมาก ตาลาย
3. เมื่อกด Ctrl+C จะเกิด Traceback แดงเถือกพังทลายดูไม่เป็นมืออาชีพ

✅ เมื่อมี Rich Presentation Cockpit:

1. มี Spinner อนิเมชั่นบอกตลอด เช่น "กำลังคิดรอบที่ 2...", "กำลังรัน mvn test..." ทำให้มนุษย์อุ่นใจ
2. แสดง Thought เป็นกล่องสีเหลือง, Action เป็นกล่องสีฟ้า และผลลัพธ์เป็นกล่องสีเขียว กวาดสายตาตรวจได้ใน 2 วินาที
3. มี Diff สีสันสดใส และรองรับการปิดโปรแกรมอย่างสง่างาม 100%

💻 ส่วนที่ 4: ซอร์สโค้ดจริง & คำอธิบายทีละบรรทัด (Line-by-Line Implementation)
📄 1. requirements.txt และ core/__init__.py ลงทะเบียนไลบรารี rich และส่งออก TerminalUI
# 1.1 ไฟล์ requirements.txt (อัปเดตเพิ่ม rich)
ollama>=0.4.0
chromadb>=0.4.24
rich>=13.7.0

# -------------------------------------------------------------

# 1.2 ไฟล์ core/__init__.py (อัปเดต Export TerminalUI)
"""
Core Package ของ Autonomous Software Engineering Agent
[อัปเดต Day 11]: เพิ่ม TerminalUI สำหรับ Production CLI Cockpit
"""
from core.client import OllamaLLMClient
from core.parser import StructuredOutputParser, JSONDecodeError
from core.dispatcher import ToolDispatcher, ToolExecutionError
from core.engine import ReActAgentEngine, MaxIterationsReachedError
from core.ui import TerminalUI

__all__ = [
    "OllamaLLMClient",
    "StructuredOutputParser",
    "JSONDecodeError",
    "ToolDispatcher",
    "ToolExecutionError",
    "ReActAgentEngine",
    "MaxIterationsReachedError",
    "TerminalUI"
]
📄 2. core/ui.py (ไฟล์ใหม่ประจำ Day 11) เอนจินจัดแต่งหน้าจอ Terminal ระดับโปรดักชันด้วย Rich
import sys
from typing import Optional, Any
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.markdown import Markdown
from rich.syntax import Syntax
from rich.text import Text

class TerminalUI:
    """
    ตัวจัดการการแสดงผลบน Terminal ระดับ Production (Presentation Layer)
    ใช้ไลบรารี Rich เพื่อสร้างประสบการณ์ผู้ใช้เทียบเท่า CLI สากล
    """
    def __init__(self):
        # 1. สร้าง Console กลางสำหรับควบคุมการเรนเดอร์ทั้งหมด
        self.console = Console()

    def print_banner(self, model_name: str, max_iterations: int) -> None:
        """วาด Banner ต้อนรับเข้าสู่ Cockpit พร้อมข้อมูลระบบ"""
        banner_text = Text()
        banner_text.append("🤖 LOCAL SE AGENT COCKPIT\n", style="bold magenta")
        banner_text.append("Autonomous Engineering Companion บนชิป Apple Silicon M3\n\n", style="italic slate-300")
        banner_text.append(f"📦 Active Model: {model_name} | 🛡️ Guardrail Limit: {max_iterations} steps\n", style="cyan")
        banner_text.append("🔒 100% Local • 0% Cloud Leak • Free Forever", style="green")

        panel = Panel(
            banner_text,
            title="[bold yellow]Personal AI Workstation[/bold yellow]",
            subtitle="[slate-500]Phase 1.5 Standard[/slate-500]",
            border_style="magenta",
            padding=(1, 2)
        )
        self.console.print(panel)

    def print_thought(self, step: int, total_steps: int, thought: str) -> None:
        """แสดงกระบวนการคิด (Chain-of-Thought) ของโมเดลในกรอบสีม่วง/เหลือง"""
        md = Markdown(thought)
        panel = Panel(
            md,
            title=f"[bold yellow]💡 Step {step}/{total_steps} • Agent Thought[/bold yellow]",
            border_style="yellow",
            padding=(0, 1)
        )
        self.console.print(panel)

    def print_action(self, tool_name: str, arguments: dict) -> None:
        """แสดงคำสั่งการเรียกใช้เครื่องมือ (Tool Action) พร้อมตารางพารามิเตอร์"""
        table = Table(show_header=True, header_style="bold cyan", border_style="slate-800", box=None)
        table.add_column("Parameter", style="cyan", width=20)
        table.add_column("Value", style="white")

        for k, v in arguments.items():
            table.add_row(str(k), str(v))

        panel = Panel(
            table,
            title=f"[bold cyan]🛠️ Tool Invocation: {tool_name}[/bold cyan]",
            border_style="cyan",
            padding=(0, 1)
        )
        self.console.print(panel)

    def print_observation(self, observation: str) -> None:
        """แสดงผลลัพธ์จากการรันเครื่องมือ (Observation)"""
        obs_str = str(observation).strip()
        # ตัดทอนหากข้อความยาวเกินไป เพื่อไม่ให้รกหน้าจอ แต่ยังคงสาระสำคัญ
        if len(obs_str) > 500:
            display_text = obs_str[:500] + "\n\n... [ข้อความยาวเกิน 500 ตัวอักษร ถูกตัดทอนในการแสดงผล] ..."
        else:
            display_text = obs_str

        panel = Panel(
            Text(display_text, style="slate-300"),
            title="[bold green]👁️ Observation Result[/bold green]",
            border_style="green",
            padding=(0, 1)
        )
        self.console.print(panel)

    def print_diff(self, diff_text: str, filename: str) -> None:
        """แสดง Unified Diff พร้อมไฮไลต์สีเขียว/แดงแบบ Git"""
        if not diff_text.strip():
            self.console.print(f"[yellow]ℹ️ ไม่มีเนื้อหาความต่างในไฟล์ {filename}[/yellow]")
            return

        # ใช้ Rich Syntax ในภาษา diff เพื่อไฮไลต์ + และ - โดยอัตโนมัติ
        syntax = Syntax(diff_text, "diff", theme="monokai", line_numbers=False)
        panel = Panel(
            syntax,
            title=f"[bold yellow]🔍 Unified Diff Preview: {filename}[/bold yellow]",
            border_style="yellow",
            padding=(0, 1)
        )
        self.console.print(panel)

    def print_final_answer(self, final_answer: str) -> None:
        """แสดงผลสรุปงานสุดท้าย (Final Answer) ในกรอบสีเขียวสมบูรณ์แบบ"""
        md = Markdown(final_answer)
        panel = Panel(
            md,
            title="[bold green]🎯 Mission Accomplished • Final Report[/bold green]",
            border_style="bold green",
            padding=(1, 2)
        )
        self.console.print(panel)

    def status(self, message: str):
        """Context Manager สำหรับแสดง Live Spinner หมุนวนขณะกำลังทำงาน"""
        return self.console.status(f"[bold yellow]{message}[/bold yellow]", spinner="dots")

    def print_error(self, message: str) -> None:
        """แสดงข้อความแจ้งเตือนความผิดพลาดในกรอบสีแดง"""
        self.console.print(Panel(Text(message, style="bold red"), title="[bold red]🛑 System Alert[/bold red]", border_style="red"))

    def prompt_user(self, prompt_text: str = "🧑‍💻 คุณ > ") -> str:
        """รับข้อความคำสั่งจากผู้ใช้"""
        try:
            return self.console.input(f"\n[bold magenta]{prompt_text}[/bold magenta]").strip()
        except (KeyboardInterrupt, EOFError):
            return "exit"
ชำแหละไวยากรณ์สำคัญใน core/ui.py
from rich.console import Console; self.console = Console()

Terminal Renderer Central: หัวใจของ Rich ที่ตรวจจับขนาดความกว้างหน้าจอ Terminal ของ Mac และรองรับ ANSI Color Codes แบบ 24-bit TrueColor

self.console.status(message, spinner="dots")

Live Background Spinner: Context Manager ที่สร้าง Thread เบื้องหลังเพื่อหมุนอนิเมชั่นจุดไข่ปลาบน Terminal ป้องกันปัญหาหน้าจอค้างนิ่งสนิทขณะรอ Ollama หรือ Maven

Syntax(diff_text, "diff", theme="monokai")

Lexer-based Code Highlight: ตัวแปลงข้อความ Diff ให้ออกสีเขียว (+) สำหรับบรรทัดเพิ่ม และสีแดง (-) สำหรับบรรทัดลบแบบเดียวกับ GitHub หรือ VS Code

📄 3. main.py (อัปเกรดเชื่อมต่อ TerminalUI เต็มรูปแบบ) ห้องบังคับการ CLI อัจฉริยะที่สวยงามและรับมือเหตุการณ์ไม่คาดคิด
import sys
import argparse
from core import (
    OllamaLLMClient,
    ToolDispatcher,
    ReActAgentEngine,
    MaxIterationsReachedError,
    TerminalUI
)
from core.tools import read_file, run_maven_test, apply_code_patch, rollback_file

DEFAULT_SYSTEM_PROMPT = (
    "You are an Autonomous Senior Software Engineering Agent running locally on Apple Silicon Mac.\n"
    "You operate in a strict ReAct loop (Reason, Act, Observe).\n"
    "You have access to tools to inspect local code, run Maven tests, and safely apply refactoring patches.\n\n"
    "Available Tools:\n"
    "1. read_file(filepath: string): Reads file content safely from workspace.\n"
    "2. run_maven_test(project_dir: string): Runs Maven unit tests for a Java project.\n"
    "3. apply_code_patch(filepath: string, new_code: string): Safely applies code patch with automatic backup and diff.\n"
    "4. rollback_file(filepath: string): Instantly restores original file from .bak backup.\n\n"
    "Response Rules:\n"
    "- When taking action, reply strictly with JSON:\n"
    "{\n"
    '  "thought": "Your reasoning why you take this step",\n'
    '  "tool": "tool_name",\n'
    '  "arguments": { ... }\n'
    "}\n\n"
    "- When task is completed, reply strictly with JSON:\n"
    "{\n"
    '  "thought": "Summary of achievements",\n'
    '  "final_answer": "Comprehensive conclusion and explanation for human developer"\n'
    "}\n\n"
    "Respond ONLY with valid JSON."
)

def create_agent(model_name: str, max_iterations: int, ui: TerminalUI) -> ReActAgentEngine:
    """Factory Function: ประกอบร่างระบบพร้อมเชื่อมต่อ UI"""
    with ui.status(f"กำลังเชื่อมต่อ Ollama Daemon และตรวจสอบโมเดล '{model_name}'..."):
        client = OllamaLLMClient(model_name=model_name)
        if not client.check_health():
            ui.print_error(f"ไม่พบโมเดล '{model_name}' หรือ Ollama Daemon ไม่ได้เปิดทำงาน!\nกรุณารันคำสั่ง 'ollama list' หรือ 'ollama serve'")
            sys.exit(1)

    # ลงทะเบียน Tools ทั้ง 4 ชิ้น (Reader, Runner, Refactor, Rollback)
    dispatcher = ToolDispatcher()
    dispatcher.register("read_file", read_file)
    dispatcher.register("run_maven_test", run_maven_test)
    dispatcher.register("apply_code_patch", apply_code_patch)
    dispatcher.register("rollback_file", rollback_file)

    return ReActAgentEngine(client=client, dispatcher=dispatcher, max_iterations=max_iterations)

def run_single_task(agent: ReActAgentEngine, task: str, ui: TerminalUI) -> None:
    """สั่งประมวลผลโจทย์ 1 งานพร้อมแสดงผลผ่าน UI"""
    ui.console.print(f"\n[bold cyan]🎯 เริ่มต้นปฏิบัติภารกิจ:[/bold cyan] [italic white]\"{task}\"[/italic white]\n" + "─" * 60)
    try:
        # เริ่มลูป ReAct
        final_answer = agent.run(user_prompt=task, system_prompt=DEFAULT_SYSTEM_PROMPT)
        ui.print_final_answer(final_answer)
    except MaxIterationsReachedError as err:
        ui.print_error(f"Guardrail Alert: {err}")
    except KeyboardInterrupt:
        ui.console.print("\n[yellow]⚠️ ผู้ใช้สั่งยกเลิกงานกลางคัน (Ctrl+C)[/yellow]")
    except Exception as err:
        ui.print_error(f"เกิดข้อผิดพลาดไม่คาดคิด: {err}")

def run_interactive_mode(agent: ReActAgentEngine, ui: TerminalUI) -> None:
    """เปิดโหมดห้องบังคับการ REPL Shell พูดคุยต่อเนื่อง"""
    ui.console.print("\n[bold magenta]💬 เข้าสู่โหมด Interactive Cockpit Shell[/bold magenta] [slate-500](พิมพ์ 'exit' หรือ 'quit' เพื่อออก)[/slate-500]")
    ui.console.print("─" * 60)
    while True:
        user_input = ui.prompt_user()
        if not user_input:
            continue
        if user_input.lower() in ["exit", "quit", "q"]:
            ui.console.print("\n[bold green]👋 ลาก่อนครับ! ขอบคุณที่ใช้งาน Local SE Agent Cockpit[/bold green]")
            break

        run_single_task(agent, user_input, ui)

def main():
    parser = argparse.ArgumentParser(description="Local SE Agent Production Rich CLI")
    parser.add_argument("-t", "--task", type=str, help="คำสั่งงานเดี่ยว เช่น: -t 'ตรวจบั๊กใน sample_maven_project'")
    parser.add_argument("-i", "--interactive", action="store_true", help="เปิดโหมด Interactive REPL Prompt")
    parser.add_argument("-m", "--model", type=str, default="qwen2.5-coder:7b", help="ชื่อโมเดล Ollama")
    parser.add_argument("--max-iterations", type=int, default=6, help="จำกัดรอบสูงสุด")

    args = parser.parse_args()
    ui = TerminalUI()

    # แสดง Banner ต้อนรับ
    ui.print_banner(model_name=args.model, max_iterations=args.max_iterations)

    # สร้าง Agent
    agent = create_agent(model_name=args.model, max_iterations=args.max_iterations, ui=ui)

    if args.task:
        run_single_task(agent, args.task, ui)
    elif args.interactive or len(sys.argv) == 1:
        run_interactive_mode(agent, ui)

if __name__ == "__main__":
    main()
📄 4. test_rich_ui.py (สคริปต์ทดสอบคอมโพเนนต์ UI ทั้งหมด) ทดลองเรนเดอร์ Banner, Panels, Spinners, Tables และ Diff
import time
from core.ui import TerminalUI

def main():
    ui = TerminalUI()

    # 1. ทดสอบ Banner
    ui.print_banner(model_name="qwen2.5-coder:7b", max_iterations=6)
    time.sleep(1)

    # 2. ทดสอบ Live Status Spinner
    with ui.status("กำลังจำลองการคิดและรันคำสั่งเบื้องหลัง 2 วินาที..."):
        time.sleep(2)

    # 3. ทดสอบกล่อง Thought
    ui.print_thought(
        step=1,
        total_steps=6,
        thought="ฉันตรวจสอบพบว่า Unit Test ใน `CalculatorTest.java` ล้มเหลว เนื่องจากสูตรลดราคาผิด"
    )

    # 4. ทดสอบกล่อง Action Table
    ui.print_action(
        tool_name="apply_code_patch",
        arguments={"filepath": "Calculator.java", "lines_changed": 3}
    )

    # 5. ทดสอบพรีวิว Unified Diff
    sample_diff = (
        "--- a/Calculator.java\n"
        "+++ b/Calculator.java\n"
        "@@ -3,2 +3,2 @@\n"
        "-        return price - (discount * 2.0);\n"
        "+        return price - discount;\n"
    )
    ui.print_diff(diff_text=sample_diff, filename="Calculator.java")

    # 6. ทดสอบกล่อง Observation
    ui.print_observation("BUILD SUCCESS: การรันชุดทดสอบผ่าน 100% เรียบร้อยแล้ว!")

    # 7. ทดสอบกล่อง Final Report
    ui.print_final_answer(
        "### สรุปผลการปฏิบัติงาน\n"
        "- แก้ไขบั๊กใน `Calculator.java` เรียบร้อย\n"
        "- รัน `mvn test` ผ่านฉลุย 100%\n"
        "- สร้างสำเนาแบ็กอัป `.bak` เรียบร้อย ปลอดภัย 100%"
    )

    print("\n🎉 ผ่านการทดสอบคอมโพเนนต์ UI ทั้งหมด 100%! สวยงามระดับ Copilot Production Standard!")

if __name__ == "__main__":
    main()
⚡ ส่วนที่ 5: ปฏิบัติการจริงบน Terminal Mac M3 (Step-by-Step Lab)

เปิด Terminal บน MacBook M3 แล้วทำตาม 5 ขั้นตอนนี้เพื่อติดตั้งไลบรารี rich และเปิดใช้งานห้องบังคับการใหม่ของคุณทันที:

ขั้นตอนที่ 1: เข้าโฟลเดอร์โปรเจกต์และเปิด Virtual Environment
cd ~/se_agent
source .venv/bin/activate
ขั้นตอนที่ 2: ติดตั้ง Library Rich ลงใน Virtual Environment
pip install "rich>=13.7.0"

ไลบรารี Rich มีขนาดเบามาก ติดตั้งเสร็จในเวลาไม่กี่วินาทีบน Mac

ขั้นตอนที่ 3: สร้างไฟล์ใหม่สำหรับ Day 11
touch core/ui.py test_rich_ui.py
ขั้นตอนที่ 4: วางโค้ดลงในแต่ละไฟล์

- อัปเดตไฟล์ requirements.txt และ core/__init__.py ตาม ส่วนที่ 4 (ไฟล์ที่ 1)
- นำโค้ดใน ส่วนที่ 4 (ไฟล์ที่ 2) ไปวางใน core/ui.py
- นำโค้ดใน ส่วนที่ 4 (ไฟล์ที่ 3) ไปอัปเดตทับไฟล์ main.py
- นำโค้ดใน ส่วนที่ 4 (ไฟล์ที่ 4) ไปวางใน test_rich_ui.py

ขั้นตอนที่ 5: สั่งรันสคริปต์ทดสอบ UI Component
python test_rich_ui.py

🎉 ผลลัพธ์: คุณจะเห็น Terminal เปล่งประกายด้วย Banner สีม่วง/ทอง, อนิเมชั่น Spinner จุดไข่ปลาหมุนวน, กล่อง Thought สีเหลือง, กล่อง Action สีฟ้า, ตารางพารามิเตอร์ และ Unified Diff สีเขียว/แดงอย่างสวยงาม!

ขั้นตอนที่ 6 (Bonus): เปิดใช้งาน Cockpit จริงในโหมด Interactive
python main.py --interactive

พิมพ์คำสั่งคุยกับ Agent เช่น "ช่วยตรวจบั๊กใน sample_maven_project แล้วแก้ให้เทสผ่าน" แล้วชม AI ทำงานแบบ Real-time พร้อมกราฟิกสวยงามได้เลย!

📝 ส่วนที่ 6: ชุดควิซประเมินความรู้เชิงวิศวกรรม 15 ข้อ (ตอบปุ๊บรู้ผลทันที)

ข้อที่ 1: วัตถุประสงค์หลักของการนำไลบรารี `rich` มาสร้าง Production-Grade CLI ใน Day 11 คืออะไร?

ข้อที่ 2: ปัญหาคลาสสิกของการใช้คำสั่ง `print()` ธรรมดาขณะ Agent กำลังคิดหรือรันเทสนานๆ คืออะไร?

ข้อที่ 3: ฟังก์ชัน `console.status()` ในไลบรารี Rich ทำหน้าที่อะไรในระดับสถาปัตยกรรม?

ข้อที่ 4: คลาสใดใน Rich ที่ใช้สำหรับไฮไลต์สีไวยากรณ์โค้ดและข้อความ Unified Diff (เช่น บรรทัด + สีเขียว และ - สีแดง)?

ข้อที่ 5: การแยกโมดูล `core/ui.py` ออกจาก `core/engine.py` สอดคล้องกับหลักการออกแบบซอฟต์แวร์ข้อใด?

ข้อที่ 6: การแสดงผลข้อคิด (Thought) ในกรอบสีเหลือง และคำสั่งเรียก Tool ในกรอบสีฟ้า ช่วยมนุษย์ได้อย่างไร?

ข้อที่ 7: เมื่อผู้ใช้กด `Ctrl+C` (KeyboardInterrupt) ใน Terminal REPL Shell โค้ดที่ดีควรมีพฤติกรรมอย่างไร?

ข้อที่ 8: คอมโพเนนต์ `rich.table.Table` ถูกนำมาใช้แสดงผลส่วนใดใน TerminalUI ของเรา?

ข้อที่ 9: คอมโพเนนต์ `rich.markdown.Markdown` มีประโยชน์อย่างไรเมื่อ Agent ตอบกลับข้อความยาวๆ?

ข้อที่ 10: หาก Observation หรือ Error Log มีความยาว 2,000 บรรทัด ฟังก์ชัน `print_observation()` จัดการอย่างไร?

ข้อที่ 11: ธงคำสั่ง `-t / --task` กับ `-i / --interactive` ใน `main.py` แตกต่างกันอย่างไร?

ข้อที่ 12: การติดตั้งไลบรารี `rich` บน Mac M3 16GB มีผลกระทบต่อประสิทธิภาพเครื่องอย่างไร?

ข้อที่ 13: เมื่อเรามี Rich CLI ที่สมบูรณ์แบบใน Day 11 ใน **Day 12 (Error Handling & Safety Guardrails)** เราจะยกระดับด้านใด?

ข้อที่ 14: ทำไมการมี Production Cockpit CLI จึงทำให้คุณรู้สึกว่า Agent มีชีวิตและน่าเชื่อถือมากขึ้น?

ข้อที่ 15: ในฐานะวิศวกรซอฟต์แวร์ เมื่อคุณมีห้องบังคับการ Rich CLI Cockpit ส่วนตัวบน Mac M3 รู้สึกอย่างไร?

🏁 สรุปหมุดเชื่อมโยง Day 11 (Chapter Wrap-up)

ใน Day 11 — Production-Grade Rich CLI & Interactive REPL Shell คุณได้สร้างโมดูล core/ui.py ติดตั้งระบบ Presentation Layer ระดับอุตสาหกรรมด้วย rich อัปเกรด main.py ให้มีทั้ง Live Status Spinner ที่ป้องกันหน้าจอค้าง, Styled Panels แยก Thought/Action/Observation ชัดเจน, Syntax Highlighting Diff สีเขียว/แดง และโหมด Interactive REPL Shell ที่รับมือ Ctrl+C ได้อย่างสง่างาม ตอนนี้ Agent ของคุณมีหน้าตาห้องบังคับการระดับโปรดักชันที่สวยงามเทียบเท่า Copilot แล้ว พร้อมก้าวเข้าสู่ Day 12: Error Handling & Safety Guardrails เพื่อติดตั้งเกราะคุ้มกันความปลอดภัยขั้นสูงสุดต่อไปครับ!