5.7 KiB
5.7 KiB
Tech Stack & Constraints
Overview
This project is a standalone Rust web server binary that serves a Vite/React frontend and exposes a WebSocket API. The built frontend assets are packaged with the binary (in a frontend directory) and served as static files. It functions as an Agentic Code Assistant capable of safely executing tools on the host system.
Core Stack
- Backend: Rust (Web Server)
- MSRV: Stable (latest)
- Framework: Poem HTTP server with WebSocket support for streaming; HTTP APIs should use Poem OpenAPI (Swagger) for non-streaming endpoints.
- Frontend: TypeScript + React
- Build Tool: Vite
- Styling: CSS Modules or Tailwind (TBD - Defaulting to CSS Modules)
- State Management: React Context / Hooks
- Chat UI: Rendered Markdown with syntax highlighting.
Agent Architecture
The application follows a Tool-Use (Function Calling) architecture:
- Frontend: Collects user input and sends it to the LLM.
- LLM: Decides to generate text OR request a Tool Call (e.g.,
execute_shell,read_file). - Web Server Backend (The "Hand"):
- Intercepts Tool Calls.
- Validates the request against the Safety Policy.
- Executes the native code (File I/O, Shell Process, Search).
- Returns the output (stdout/stderr/file content) to the LLM.
- Streaming: The backend sends real-time updates over WebSocket to keep the UI responsive during long-running Agent tasks.
LLM Provider Abstraction
To support both Remote and Local models, the system implements a ModelProvider abstraction layer.
- Strategy:
- Abstract the differences between API formats (OpenAI-compatible vs Anthropic vs Gemini).
- Normalize "Tool Use" definitions, as each provider handles function calling schemas differently.
- Supported Providers:
- Ollama: Local inference (e.g., Llama 3, DeepSeek Coder) for privacy and offline usage.
- Anthropic: Claude 3.5 models (Sonnet, Haiku) via API for coding tasks (Story 12).
- Provider Selection:
- Automatic detection based on model name prefix:
claude-→ Anthropic API- Otherwise → Ollama
- Single unified model dropdown with section headers ("Anthropic", "Ollama")
- Automatic detection based on model name prefix:
- API Key Management:
- Anthropic API key stored server-side and persisted securely
- On first use of Claude model, user prompted to enter API key
- Key persists across sessions (no re-entry needed)
Tooling Capabilities
1. Filesystem (Native)
- Scope: Strictly limited to the user-selected
project_root. - Operations: Read, Write, List, Delete.
- Constraint: Modifications to
.git/are strictly forbidden via file APIs (use Git tools instead).
2. Shell Execution
- Library:
tokio::processfor async execution. - Constraint: We do not run an interactive shell (repl). We run discrete, stateless commands.
- Allowlist: The agent may only execute specific binaries:
gitcargo,rustc,rustfmt,clippynpm,node,yarn,pnpm,bunls,find,grep(if not using internal search)mkdir,rm,touch,mv,cp
3. Search & Navigation
- Library:
ignore(by BurntSushi) +greplogic. - Behavior:
- Must respect
.gitignorefiles automatically. - Must be performant (parallel traversal).
- Must respect
Coding Standards
Rust
- Style:
rustfmtstandard. - Linter:
clippy- Must pass with 0 warnings before merging. - Error Handling: Custom
AppErrortype derivingthiserror. All Commands returnResult<T, AppError>. - Concurrency: Heavy tools (Search, Shell) must run on
tokiothreads to avoid blocking the UI. - Quality Gates:
cargo clippy --all-targets --all-featuresmust show 0 errors, 0 warningscargo checkmust succeedcargo nextest runmust pass all tests
TypeScript / React
- Style: Biome formatter (replaces Prettier/ESLint).
- Linter: Biome - Must pass with 0 errors, 0 warnings before merging.
- Types: Shared types with Rust (via
tauri-spectaor manual interface matching) are preferred to ensure type safety across the bridge. - Testing: Vitest for unit/component tests; Playwright for end-to-end tests.
- Quality Gates:
npx @biomejs/biome check src/must show 0 errors, 0 warningsnpm run buildmust succeednpx vitest runmust passnpx playwright testmust pass- No
anytypes allowed (use proper types orunknown) - React keys must use stable IDs, not array indices
- All buttons must have explicit
typeattribute
Libraries (Approved)
- Rust:
serde,serde_json: Serialization.ignore: Fast recursive directory iteration respecting gitignore.walkdir: Simple directory traversal.tokio: Async runtime.reqwest: For LLM API calls (Anthropic, Ollama).eventsource-stream: For Server-Sent Events (Anthropic streaming).uuid: For unique message IDs.chrono: For timestamps.poem: HTTP server framework.poem-openapi: OpenAPI (Swagger) for non-streaming HTTP APIs.
- JavaScript:
react-markdown: For rendering chat responses.vitest: Unit/component testing.playwright: End-to-end testing.
Safety & Sandbox
- Project Scope: The application must strictly enforce that it does not read/write outside the
project_rootselected by the user. - Human in the Loop:
- Shell commands that modify state (non-readonly) should ideally require a UI confirmation (configurable).
- File writes must be confirmed or revertible.