# Arsitektur Sistem Zesdex ## Gambaran Umum Zesdex adalah autonomous AI coding agent berbasis TUI, dibangun dengan **Rust** menggunakan clean architecture berlapis. LLM client dibungkus dalam tool-use harness dengan 37+ built-in tools — file ops, git, shell, LSP, MCP, subagent orchestration, dan lainnya. ## Struktur Workspace ``` zesdex/ ├── apps/ │ ├── domain/ # Layer 1: Pure entities, traits, value objects │ ├── application/ # Layer 2: Use-case services │ ├── infrastructure/ # Layer 3: Semua I/O (LLM, DB, tools, MCP, LSP) │ ├── interfaces/ │ │ ├── tui/ # Ratatui terminal UI │ │ ├── api/ # Axum REST API │ │ ├── daemon/ # Unix socket daemon │ │ ├── ws/ # WebSocket server │ │ ├── grpc/ # gRPC server │ │ └── web/ # Web frontend │ ├── gateway/ # CLI entry point & dispatcher │ └── bootstrap/ # Initial data seeder ``` ## Dependency Graph Antar Layer ``` gateway/bootstrap │ ▼ interfaces/* (tui, api, daemon, ws, grpc, web) │ ▼ infrastructure ─── implements ──▶ domain ports │ ▼ application ─── depends on ──▶ domain traits │ ▼ domain (zero framework deps: serde, chrono, uuid only) ``` > **Aturan**: layer bawah tidak boleh tahu tentang layer atas. `domain` tidak import apapun dari `infrastructure` atau `interfaces`. ## Process Modes | Mode | Flag | Keterangan | |------|------|------------| | **TUI** | *(default)* | TUI + agent loop dalam satu proses | | **Daemon** | `--daemon` | Agent berjalan di background via IPC socket | | **Attach** | `--attach ` | TUI terhubung ke daemon yang sedang berjalan | | **REST API** | `--api` | HTTP server (default port 8080) | | **WebSocket** | `--ws` | WS server (default port 8081) | | **gRPC** | `--grpc` | gRPC server (default port 50051) | | **Web** | `--web` | Static web frontend (default port 3000) | ## Alur Data (Single-Process Mode) ``` Keyboard/Event │ ▼ controller/input.rs: handle_key() │ returns Vec ▼ action.rs: apply_action(&mut AppStateRest) │ state dimutasi in-place ├──▶ turn.rs: spawn_agent_turn() ──▶ background thread │ │ │ ├─ LLM call (blocking reqwest) │ ├─ tool execution (Tool trait) │ └─ push TurnEvent ke queue │ ▼ run.rs: run_loop_inner() │ drain TurnEvent setiap tick │ skip render jika dirty=false ▼ view/: draw frame ke terminal (ratatui) ``` ## File Kunci | File | Peran | |------|-------| | `apps/gateway/src/main.rs` | CLI entry point, parse args, dispatch ke mode | | `apps/interfaces/tui/src/state.rs` | `AppStateRest` — single source of truth state TUI | | `apps/interfaces/tui/src/action.rs` | `apply_action()` — satu-satunya tempat state dimutasi | | `apps/interfaces/tui/src/run.rs` | Event loop: render → poll → handle → tick | | `apps/interfaces/tui/src/turn.rs` | Spawn agent turn di background thread | | `apps/interfaces/tui/src/view/mod.rs` | Top-level render pipeline + `pre_render` hook | | `apps/infrastructure/src/llm/` | LLM client (streaming + non-streaming) | | `apps/infrastructure/src/tools/` | 37 tool implementations | | `apps/domain/src/core/` | Entity inti: `ChatMessage`, `Role`, `Store`, `Tool` trait | ## IPC Protocol (Daemon Mode) ``` ┌──────────┐ Unix domain socket ┌──────────┐ │ Client │ ◄──────────────────► │ Daemon │ │ (TUI) │ [4-byte len][JSON] │ (agent) │ └──────────┘ └──────────┘ Client ──Action──▶ Daemon (apply_action → state mutasi) Daemon ──StatePayload──▶ Client (render snapshot) ``` ## Lints & Kualitas Kode Semua workspace crate menerapkan lint ketat di `Cargo.toml`: - `unused`, `dead_code`, `unreachable_code` → **deny** - `unused_imports`, `unused_variables`, `unused_mut` → **deny** - `clippy::all` + `clippy::pedantic` → **warn** ## Release Profile `opt-level=3`, `lto="fat"`, `codegen-units=1`, `panic="abort"`, `strip="symbols"`