Refactor view modules for improved readability and consistency
- Updated markdown rendering logic to use more concise methods for obtaining vector lengths. - Changed review status display to use the correct flag from settings. - Cleaned up sidebar rendering code for better formatting and readability. - Enhanced status bar rendering with improved string formatting and consistent style application. - Refined workflow panel rendering, ensuring consistent style usage and improved readability. - Added architecture overview and detailed documentation for backend, data, dependencies, and frontend structures.
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
# Architecture Overview
|
||||
|
||||
## System Layout
|
||||
|
||||
Zesdex is an autonomous AI coding agent with a TUI — an LLM client wrapped in a tool-use harness with 37 built-in tools.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Process Mode │
|
||||
│ Single-Process ─── Daemon (background) ─── Attach (client) │
|
||||
└──────────────────────────┬──────────────────────────────────┘
|
||||
│ IPC (Unix domain socket)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ src/main.rs │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌────────────────┐ │
|
||||
│ │ Controller │──▶│ Runtime │──▶│ View │ │
|
||||
│ │ (input.rs) │ │ (actions.rs) │ │ (chat,status,…)│ │
|
||||
│ └──────────────┘ └──────┬───────┘ └────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────▼────────┐ │
|
||||
│ │ Harness │ │
|
||||
│ │ (tool dispatch)│ │
|
||||
│ └───────┬────────┘ │
|
||||
│ │ │
|
||||
│ ┌─────────────────┼─────────────────┐ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌─────────┐ ┌────────────┐ ┌───────────────┐ │
|
||||
│ │ Tools │ │ Subagents │ │ Workflow │ │
|
||||
│ │ (37x) │ │ (auto/gen) │ │ Engine │ │
|
||||
│ └─────────┘ └────────────┘ │ (hive_mind) │ │
|
||||
│ └───────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Process Modes
|
||||
|
||||
| Mode | Description |
|
||||
|------|-------------|
|
||||
| **Single-process** | TUI + agent run in the same process. Simplest mode. |
|
||||
| **Daemon** | `--daemon` flag. Agent processes state in background; clients attach to render. |
|
||||
| **Attach** | `--attach <id>` flag. Connect to existing daemon with IPC. |
|
||||
|
||||
In daemon mode, the daemon runs the full agent loop; clients are stateless renderers that sync via Unix domain sockets with diff-based state synchronization.
|
||||
|
||||
## Data Flow
|
||||
|
||||
1. **Input** → `controller/input.rs` handles key events and autocomplete
|
||||
2. **Dispatch** → `app/runtime/actions/mod.rs` applies actions to state (`AppStateRest`)
|
||||
3. **LLM Stream** → `app/runtime/stream/mod.rs` parses SSE chunks into typed events
|
||||
4. **Tool Execution** → `app/harness.rs` gates and runs tool calls via the `Tool` trait
|
||||
5. **Rendering** → `view/` modules read `AppStateRest` and render via ratatui
|
||||
|
||||
## Key Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `src/main.rs` | Entry point, process mode dispatch, TUI init |
|
||||
| `src/app/state/rest.rs` | Single source-of-truth state struct |
|
||||
| `src/app/runtime/actions/mod.rs` | State reducer (`apply_action`) |
|
||||
| `src/app/runtime/stream/mod.rs` | SSE stream parser |
|
||||
| `src/app/harness.rs` | Tool harness with safety gating |
|
||||
| `src/app/workflow/hive_mind.rs` | Multi-agent orchestration |
|
||||
| `src/tool/mod.rs` | Tool trait + registry (37 tools) |
|
||||
| `src/view/mod.rs` | TUI render pipeline |
|
||||
@@ -0,0 +1,68 @@
|
||||
# Backend Architecture
|
||||
|
||||
## Provider Layer
|
||||
|
||||
The provider abstraction in `dto/provider/` and `service/provider.rs` wraps LLM API calls:
|
||||
|
||||
- **Configuration**: `model/app_config.rs` loads Anthropic/OpenAI-compatible endpoint settings
|
||||
- **Authentication**: `service/oauth/` handles OAuth 2.0 with PKCE flow and token management
|
||||
- **Requests**: `dto/provider/request.rs` builds provider-agnostic request structs
|
||||
- **Responses**: `dto/provider/response.rs` parses streaming and non-streaming responses
|
||||
- **Token tracking**: `dto/provider/usage.rs` tracks token consumption
|
||||
|
||||
## IPC (Inter-Process Communication)
|
||||
|
||||
The daemon-client protocol in `src/ipc/`:
|
||||
|
||||
- **Transport**: Unix domain sockets
|
||||
- **Framing**: Length-prefixed frames with `serde_json` serialization (`ipc/frame.rs`)
|
||||
- **State Sync**: Full state push from daemon after each action (`ipc/snapshot.rs`); diff-based updates for efficiency (`ipc/diff.rs`)
|
||||
- **Protocol**: `ipc/protocol.rs` defines message types (Action, StateSnapshot, etc.)
|
||||
|
||||
Flow:
|
||||
```
|
||||
Client ──Action──▶ Daemon ──apply_action()──▶ State mutated
|
||||
│
|
||||
└──StatePayload──▶ Client (render)
|
||||
```
|
||||
|
||||
## Workflow Engine
|
||||
|
||||
Located in `src/app/workflow/`:
|
||||
|
||||
- **Script DSL** (`engine.rs`): Executes the workflow script language (agent/parallel/pipeline/phase). Supports subagent spawning with schema-validated output, concurrency limiting, and budget tracking.
|
||||
- **Hive Mind** (`hive_mind.rs`): Core Intelligence spawns a CognitiveCyclePlan — ordered cycles of parallel processing nodes. Each node has a directive and access tier (`read`/`write`/`full`). Node outputs merge into a shared collective state in real time. Final consensus synthesis completes the convergence.
|
||||
- **Docs** (`docs.rs`): Deterministic (not LLM) convergence writer — records every node's output + final consensus to `docs/runs/`.
|
||||
|
||||
## MCP (Model Context Protocol)
|
||||
|
||||
`src/app/mcp/manager.rs` manages MCP client connections:
|
||||
|
||||
- Uses the `rmcp` crate for the MCP protocol
|
||||
- Supports stdio-based transport (child process) and streamable HTTP
|
||||
- Tool discovery via `list_tools()` and dynamic tool registration
|
||||
|
||||
## LSP Integration
|
||||
|
||||
`src/app/lsp/` provides Language Server Protocol support:
|
||||
|
||||
- **Auto-provisioner** (`provisioner.rs`): Detects and starts LSP servers for Rust, TypeScript, Python, Go, and other languages
|
||||
- **Client** (`client.rs`): JSON-RPC-based LSP client with typed notifications
|
||||
- **Tools** (`tool/lsp/mod.rs`): 7 LSP tools (connect, hover, completion, definition, references, diagnostics, disconnect)
|
||||
|
||||
## Background Bash
|
||||
|
||||
`src/app/bgbash/` manages long-running shell jobs:
|
||||
|
||||
- **Control** (`control.rs`): Job lifecycle management (spawn, signal, terminate) using Unix process groups
|
||||
- **Job** (`job.rs`): Individual job state tracking with output buffering and progress monitoring
|
||||
|
||||
## Review System
|
||||
|
||||
`src/app/subagent/auto.rs` spawns background reviews:
|
||||
|
||||
- Quick review after every edit
|
||||
- Background test generation
|
||||
- Architecture review
|
||||
- Security review
|
||||
- All retry once on failure, escalate to blocking error if retry also fails
|
||||
@@ -0,0 +1,89 @@
|
||||
# Data Architecture
|
||||
|
||||
## State Model
|
||||
|
||||
The single source of truth is `AppStateRest` (`src/app/state/rest.rs`):
|
||||
|
||||
```
|
||||
AppStateRest
|
||||
├── session: SessionRuntime (hive_mind state, convergence flag)
|
||||
├── runtime: RuntimeState (mode, provider status)
|
||||
├── chat: ChatState (messages, scroll)
|
||||
├── input: InputState (text, cursor, autocomplete)
|
||||
├── settings: Settings (provider, model, temperature, concise_output)
|
||||
├── config: AppConfig (endpoints, credentials)
|
||||
├── scroll: ScrollState (per-panel offset)
|
||||
├── diff: DiffState (edit review)
|
||||
├── tools: Vec with outputs
|
||||
├── statusline, sidebar, etc.
|
||||
└── toasts: pending notifications
|
||||
```
|
||||
|
||||
**Mutation rules** (per CLAUDE.md):
|
||||
- Mutated in-place from exactly two locations: `actions/mod.rs` (apply_action) and `controller/input.rs` (key handlers)
|
||||
- Read-only from every other module
|
||||
- No generic update function — direct field mutation only
|
||||
|
||||
## Persistence
|
||||
|
||||
### SQLite Message Log (`src/model/msglog/`)
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `schema.rs` | Table definitions (messages, sessions) |
|
||||
| `mod.rs` | CRUD operations |
|
||||
| `query.rs` | Query helpers (search, filter) |
|
||||
| `blobs.rs` | Large message blob storage |
|
||||
| `summary.rs` | Conversation summary cache |
|
||||
|
||||
Schema uses `rusqlite` (bundled) with per-session isolation — each session gets its own database.
|
||||
|
||||
### Memory System (`src/model/memory.rs`)
|
||||
|
||||
File-based memory stored under `~/.claude/projects/<project>/memory/`:
|
||||
|
||||
- Each memory is one markdown file with frontmatter (name, description, type)
|
||||
- Types: `user`, `feedback`, `project`, `reference`
|
||||
- Memory index in MEMORY.md
|
||||
- Export/import for lesson sharing
|
||||
- PID-file session lock prevents concurrent access
|
||||
|
||||
### Settings & Config (`src/model/`)
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `settings.rs` | Serialized user preferences (provider, model, theme) |
|
||||
| `app_config.rs` | Provider endpoints, API key resolution from env |
|
||||
| `session.rs` | Current session metadata |
|
||||
| `conversation.rs` | In-memory conversation state |
|
||||
| `editlog.rs` | Append-only JSONL edit audit trail |
|
||||
|
||||
### Edit Log
|
||||
|
||||
`src/model/editlog.rs` records every file mutation:
|
||||
|
||||
```json
|
||||
{"ts": 123, "tool": "edit", "path": "src/main.rs",
|
||||
"reason": "fix bug", "content_sha256": "abc123",
|
||||
"bytes_delta": 15, "origin": "chat", "session_id": "sess-1"}
|
||||
```
|
||||
|
||||
Max 5000 entries held in memory before pruning oldest.
|
||||
|
||||
## Context Management (`src/app/runtime/context/`)
|
||||
|
||||
| Module | Purpose |
|
||||
|--------|---------|
|
||||
| `tokens.rs` | Token counting via `tiktoken-rs` |
|
||||
| `window.rs` | Token window resolution (fit within model context) |
|
||||
| `dedup.rs` | Deduplication of repeated tool outputs |
|
||||
| `squash.rs` | Compression of large JSON tool results |
|
||||
| `shaping.rs` | Message dropping when context exceeds limits |
|
||||
|
||||
## IPC Data Flow
|
||||
|
||||
```
|
||||
Daemon State ──diff──▶ serialize ──frame──▶ socket ──▶ Client
|
||||
│
|
||||
Client State ◀── apply_diff ◀── deserialize ◀──── socket ─┘
|
||||
```
|
||||
@@ -0,0 +1,99 @@
|
||||
# Dependencies
|
||||
|
||||
## Rust Crates (30+ direct)
|
||||
|
||||
### Core Framework
|
||||
| Crate | Version | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `ratatui` | 0.30.2 | TUI framework |
|
||||
| `crossterm` | 0.29 | Terminal manipulation |
|
||||
| `tokio` | 1 | Async runtime (multi-thread, macros, sync, time, net, io-util, signal) |
|
||||
|
||||
### HTTP & Networking
|
||||
| Crate | Version | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `reqwest` | 0.13 | HTTP client (JSON, streaming, native-tls-vendored, form) |
|
||||
| `rmcp` | 2.2 | MCP client (child-process, streamable HTTP) |
|
||||
| `webbrowser` | 1 | Open URLs in browser |
|
||||
| `url` | 2 | URL parsing |
|
||||
| `percent-encoding` | 2 | URL encoding |
|
||||
|
||||
### HTML/Markdown
|
||||
| Crate | Version | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `dom_smoothie` | 0.18.0 | HTML DOM manipulation |
|
||||
| `fast_html2md` | 0.0.62 | HTML-to-Markdown conversion |
|
||||
| `scraper` | 0.27.0 | HTML parsing/selecting |
|
||||
| `pulldown-cmark` | 0.13 | Markdown parsing (no default features) |
|
||||
|
||||
### Serialization
|
||||
| Crate | Version | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `serde` | 1 | Serialization framework |
|
||||
| `serde_json` | 1 | JSON serialization |
|
||||
| `serde_yaml_ng` | 0.10 | YAML serialization |
|
||||
|
||||
### Storage & Files
|
||||
| Crate | Version | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `rusqlite` | 0.40 | SQLite (bundled) |
|
||||
| `ignore` | 0.4 | `.gitignore`-aware file walking |
|
||||
| `globset` | 0.4 | Glob pattern matching |
|
||||
| `include_dir` | 0.7 | Embed directory contents in binary |
|
||||
| `infer` | 0.19 | File type detection |
|
||||
| `dirs` | 6 | Standard OS directories |
|
||||
|
||||
### Text & Search
|
||||
| Crate | Version | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `regex` | 1 | Regular expressions |
|
||||
| `nucleo-matcher` | 0.3 | Fuzzy matching (for @mention autocomplete) |
|
||||
| `similar` | 3 | Diff computation |
|
||||
| `syntect` | 5 | Syntax highlighting |
|
||||
| `tiktoken-rs` | 0.12 | OpenAI token counting |
|
||||
|
||||
### Cryptography & Encoding
|
||||
| Crate | Version | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `base64` | 0.22 | Base64 encoding |
|
||||
| `sha2` | 0.11 | SHA-256 hashing |
|
||||
| `hex` | 0.4 | Hex encoding |
|
||||
| `uuid` | 1 | UUID generation (v4, v5) |
|
||||
| `libc` | 0.2 | Raw C FFI bindings |
|
||||
|
||||
### Error Handling & Logging
|
||||
| Crate | Version | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `anyhow` | 1 | Error handling |
|
||||
| `tracing` | 0.1 | Structured logging |
|
||||
| `tracing-subscriber` | 0.3 | Log subscriber with env-filter |
|
||||
| `chrono` | 0.4 | Date/time with serde |
|
||||
|
||||
### Other
|
||||
| Crate | Version | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `lsp-types` | 0.97 | LSP protocol types |
|
||||
| `futures-util` | 0.3 | Async stream combinators |
|
||||
|
||||
## External Services
|
||||
|
||||
| Service | Purpose |
|
||||
|---------|---------|
|
||||
| **Anthropic API** | Primary LLM provider |
|
||||
| **OpenAI API** | Alternative LLM provider (including OAuth) |
|
||||
| **GitHub** | Release artifacts via semantic-release CI |
|
||||
| **MCP Servers** | External tool servers (stdio or HTTP) |
|
||||
| **LSP Servers** | Language servers (rust-analyzer, TypeScript, Pyright, gopls, etc.) |
|
||||
|
||||
## Build Configuration
|
||||
|
||||
### Compiler Lints (`.cargo/config.toml`)
|
||||
All unused code, dead code, and deprecation warnings promoted to errors:
|
||||
`-W unused`, `-W dead_code`, `-W unreachable_code`, `-D warnings`
|
||||
|
||||
### Release Profile
|
||||
`opt-level=3`, LTO="fat", `codegen-units=1`, `panic="abort"`, `strip="symbols"`, `overflow-checks=true`
|
||||
|
||||
### CI/CD
|
||||
- **CI**: cargo build + test + clippy on every push
|
||||
- **Release**: semantic-release with changelog generation, Cargo.toml version bump, GitHub artifact upload
|
||||
@@ -0,0 +1,79 @@
|
||||
# Frontend (TUI) Architecture
|
||||
|
||||
## Render Pipeline
|
||||
|
||||
The TUI is built with [ratatui](https://github.com/ratatui-org/ratatui) and [crossterm](https://github.com/crossterm-rs/crossterm).
|
||||
|
||||
```
|
||||
Timer tick
|
||||
│
|
||||
▼
|
||||
main.rs: fn tui_loop()
|
||||
│
|
||||
├── controller/input.rs: handle_key() → action
|
||||
├── app/runtime/actions/mod.rs: apply_action()
|
||||
│ │
|
||||
│ └── state mutates (AppStateRest)
|
||||
│
|
||||
└── view/mod.rs: build TUI layout
|
||||
│
|
||||
├── view/chat.rs: Chat transcript
|
||||
├── view/sidebar.rs: Usage dashboard
|
||||
├── view/status.rs: Status bar
|
||||
├── view/markdown.rs: Message renderer
|
||||
├── view/workflow.rs: Hive-mind progress
|
||||
└── view/theme.rs: Tokyo Night palette
|
||||
```
|
||||
|
||||
## Overlay System
|
||||
|
||||
16 overlays managed by `app/mode/`:
|
||||
|
||||
| Overlay | File | Purpose |
|
||||
|---------|------|---------|
|
||||
| Chat input | `mod.rs` | Main input bar with autocomplete |
|
||||
| Bash | `bash.rs` | Interactive shell panel |
|
||||
| Editor | `editor.rs` | Built-in file editor |
|
||||
| Effort | `effort.rs` | LLM effort selector |
|
||||
| Help | `help.rs` | Keybindings help |
|
||||
| Key Input | `key_input.rs` | Custom key binding |
|
||||
| Learning | `learning.rs` | Lesson viewer |
|
||||
| Loading | `loading.rs` | Spinner overlay |
|
||||
| MCP | `mcp.rs` | MCP server management |
|
||||
| Quit Confirm | `quit_confirm.rs` | Exit confirmation dialog |
|
||||
| Rewind | `rewind.rs` | Message/history rewind |
|
||||
| Settings | `settings.rs` | Settings panel |
|
||||
| Todo | `todo.rs` | Task/TODO list |
|
||||
| Workflow | (via view) | Workflow progress |
|
||||
|
||||
## Layout Structure
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ Status Bar (view/status.rs) │
|
||||
├──────────────────────┬──────────────────────┤
|
||||
│ │ │
|
||||
│ Chat Transcript │ Sidebar │
|
||||
│ (view/chat.rs) │ (view/sidebar.rs) │
|
||||
│ scrollable, │ tokens, status, │
|
||||
│ inline-log style │ agent info │
|
||||
│ │ │
|
||||
├──────────────────────┴──────────────────────┤
|
||||
│ Input Bar + Autocomplete dropdown │
|
||||
│ (view/mod.rs) │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Input Handling
|
||||
|
||||
`controller/input.rs`:
|
||||
|
||||
- Normal mode: keystrokes go to the active overlay
|
||||
- `@mention` triggers fuzzy autocomplete (via `nucleo-matcher`)
|
||||
- Tab cycles autocomplete candidates
|
||||
- `Ctrl+Y` copies selected text to clipboard (via OSC52 escape sequence)
|
||||
- Arrow keys scroll chat, sidebar, and other scrollable panels
|
||||
|
||||
## Theme
|
||||
|
||||
`view/theme.rs` defines a Tokyo Night color palette as constants (`Theme::PRIMARY`, `Theme::ERROR`, `Theme::TEXT_MUTED`, etc.) rather than using a theme enum or hot-reloadable config. All view modules import and apply these constants directly.
|
||||
Reference in New Issue
Block a user