# Panduan Development ## Quick Start ```bash # Build semua crate cargo build # Jalankan TUI (default) cargo run # Jalankan dengan log debug RUST_LOG=debug cargo run # Jalankan REST API cargo run -- --api --api-port 8080 # Build release cargo build --release ``` ## Struktur Workspace ``` zesdex/ ├── Cargo.toml # Workspace root, semua dependency terpusat di sini ├── Cargo.lock # Lock file (commit ini!) ├── apps/ │ ├── domain/ # Pure domain (tidak ada I/O) │ ├── application/ # Use-case services │ ├── infrastructure/ # Semua implementasi I/O │ ├── interfaces/ │ │ ├── tui/ # TUI — fokus pengembangan utama │ │ ├── api/ # REST API (Axum) │ │ ├── daemon/ # Daemon mode │ │ ├── ws/ # WebSocket │ │ ├── grpc/ # gRPC │ │ └── web/ # Web frontend │ ├── gateway/ # CLI entry point │ └── bootstrap/ # Seeder └── docs/ └── CODEMAPS/ # Dokumentasi ini ``` ## Menambah Tool Baru 1. Buat file baru di `apps/infrastructure/src/tools/.rs` 2. Implement trait `Tool`: ```rust use zesdex_domain::core::tool_call::Tool; use anyhow::Result; use serde_json::Value; pub struct MyTool; impl Tool for MyTool { fn name(&self) -> &'static str { "my_tool" } fn description(&self) -> &'static str { "Deskripsi untuk LLM" } fn parameters(&self) -> Value { serde_json::json!({ "type": "object", "properties": { "param": { "type": "string", "description": "..." } }, "required": ["param"] }) } fn run(&self, ctx: &ToolCtx, args: &Value) -> Result { let param = args["param"].as_str().unwrap_or(""); Ok(format!("Result: {param}")) } } ``` 3. Daftarkan di `apps/infrastructure/src/tools/mod.rs`: ```rust pub fn all_tools() -> Vec> { vec![ // ... tools lain ... Box::new(my_tool::MyTool), ] } ``` ## Menambah Action TUI Baru 1. Tambah variant ke `enum Action` di `apps/interfaces/tui/src/action.rs` 2. Tangani di `apply_action()` match block yang sama 3. Emit dari `controller/input.rs::handle_key()` ```rust // action.rs pub enum Action { // ... existing ... MyNewAction { data: String }, } // dalam apply_action: Action::MyNewAction { data } => { state.some_field = data; state.mark_dirty(); } ``` ## Menambah Overlay Baru 1. Buat file `apps/interfaces/tui/src/view/overlays/.rs` 2. Tambah variant ke `enum Overlay` di `state.rs` 3. Tambah entry di `overlays/mod.rs::render_overlay()` 4. Implement `pub fn render(frame, area, block, state)` di file baru ## Linting & Testing ```bash # Cek semua warnings/errors cargo clippy --all-targets # Run tests cargo test # Test satu crate saja cargo test -p zesdex-tui # Check tanpa build (cepat) cargo check --all ``` > **Penting**: Workspace ini menggunakan `deny` untuk hampir semua lint. > Kode harus compile bersih tanpa warning apapun. ## Environment Variables | Variable | Fungsi | |----------|--------| | `RUST_LOG` | Log level (`debug`, `info`, `warn`, `error`) | | `OPENAI_API_KEY` | API key LLM (jika tidak diset via settings) | | `ANTHROPIC_API_KEY` | API key Anthropic | | `ZESDEX_DATA_DIR` | Override direktori data (default: platform standard) | ## Data Directory Saat development, data disimpan di: - **Linux**: `~/.local/share/zesdex/` - **macOS**: `~/Library/Application Support/zesdex/` Untuk reset bersih: ```bash rm -rf ~/.local/share/zesdex/ ``` ## Konvensi Kode - **Tidak ada `unwrap()`** di kode produksi — gunakan `?` atau `unwrap_or_default()` - **State hanya dimutasi dari `apply_action()`** — jangan mutasi `AppStateRest` dari view - **View functions bersifat read-only** — signature `fn draw(frame: &mut Frame, state: &AppStateRest)` - **Cache mahal dikomputasi sekali** — gunakan flag `dirty` dan `pre_render` pattern - **Semua string ke LLM harus deskriptif** — nama tool dan deskripsinya penting untuk LLM context ## Release Release dilakukan via git tag semantic-release: ```bash git commit -m "feat: tambah fitur baru" # bumps minor git commit -m "fix: perbaiki bug" # bumps patch git commit -m "feat!: breaking change" # bumps major ``` CI akan otomatis: 1. Bump versi di `Cargo.toml` 2. Generate `CHANGELOG.md` 3. Build release binary 4. Upload ke GitHub Releases