diff --git a/README.md b/README.md index e646b917..e35353cd 100644 --- a/README.md +++ b/README.md @@ -2,295 +2,478 @@ # 🧠 Cortex -## Next-generation AI proxy and routing infrastructure +The AI Infrastructure Stack for Production [![CI](https://img.shields.io/github/actions/workflow/status/dallay/cortex/ci.yml?branch=main&label=CI&logo=github)](https://github.com/dallay/cortex/actions/workflows/ci.yml) [![License](https://img.shields.io/github/license/dallay/cortex)](LICENSE) -[![Rust Version](https://img.shields.io/badge/rust-1.81%2B-blue.svg)](https://www.rust-lang.org) -[![GitHub Stars](https://img.shields.io/github/stars/dallay/cortex?style=social)](https://github.com/dallay/cortex/stargazers) -[![GitHub Issues](https://img.shields.io/github/issues/dallay/cortex)](https://github.com/dallay/cortex/issues) -[![Last Commit](https://img.shields.io/github/last-commit/dallay/cortex)](https://github.com/dallay/cortex/commits/main) +[![Rust](https://img.shields.io/badge/rust-1.81%2B-DEA584?logo=rust&labelColor=4A4A4A)](https://www.rust-lang.org) +[![Node](https://img.shields.io/badge/node-20%2B-339933?logo=nodedotjs&labelColor=4A4A4A)](https://nodejs.org) +[![Vue](https://img.shields.io/badge/vue-3.4-4FC08D?logo=vuedotjs&labelColor=4A4A4A)](https://vuejs.org) +[![Docker](https://img.shields.io/badge/docker-ready-2496ED?logo=docker&labelColor=4A4A4A)](https://www.docker.com) +[![Last Commit](https://img.shields.io/github/last-commit/dallay/cortex/main?label=last%20commit)](https://github.com/dallay/cortex/commits/main) +[![Stars](https://img.shields.io/github/stars/dallay/cortex?style=flat&color=yellow)](https://github.com/dallay/cortex/stargazers) [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/dallay/cortex) -[Getting Started](#-getting-started) β€’ [Documentation](#-documentation) β€’ [Contributing](#-contributing) β€’ [Community](#-community) +**Rook** β€” AI Proxy & Router Β· **Huginn** β€” Local Coding Agent -## πŸ“‘ Table of Contents - -- [About](#-about) -- [Features](#-features) -- [Getting Started](#-getting-started) - - [Prerequisites](#prerequisites) - - [Installation](#installation) - - [Quick Start](#quick-start) -- [Usage](#-usage) -- [Configuration](#-configuration) -- [Architecture](#-architecture) -- [Tools](#-tools) -- [Development](#-development) -- [Documentation](#-documentation) -- [Roadmap](#-roadmap) -- [Contributing](#-contributing) -- [License](#-license) -- [Community](#-community) -- [Acknowledgments](#-acknowledgments) - -## πŸ“– About - -**Cortex** is a high-performance AI infrastructure project written in Rust. Its primary component, **Rook**, acts as an intelligent AI proxy and router designed to simplify and harden your AI application stack. - -In an ecosystem with multiple LLM providers (OpenAI, Anthropic, Google, etc.), Cortex provides a unified, OpenAI-compatible interface with enterprise-grade features out of the box. It solves common challenges such as provider outages, high latency, and lack of observability by providing automatic failover, efficient caching, and comprehensive audit logging. - -## ✨ Features - -- πŸ”Œ **OpenAI-compatible API**: Drop-in replacement for existing OpenAI clients. -- ✨ **Multi-provider routing**: Support for OpenAI, Anthropic, Ollama, Gemini, and Groq. -- πŸ”„ **Automatic fallback**: Resilience against provider failures with Combos (ordered fallback chains, `X-Rook-Combo`). -- 🏷️ **Model aliasing**: Normalize variant names (`gpt-4-turbo` β†’ dated canonical) with 30+ built-ins plus custom aliases. -- 🌊 **Streaming**: OpenAI-compatible SSE streaming, including tool-call deltas. -- πŸš€ **Built-in caching**: Reduce costs and latency with TTL-based in-memory caching. -- πŸ“Š **Audit logging**: Full traceability of requests and responses backed by SQLite. -- πŸ—οΈ **Clean Architecture**: Built with Domain-Driven Design (DDD) for high maintainability. -- πŸ¦€ **Rust-powered**: Exceptional performance, memory safety, and concurrency. -- πŸ”’ **Production-ready**: Includes health checks, observability (tracing, metrics), and encryption. - -## πŸš€ Getting Started +--- + +

+ What is Cortex β€’ + Products β€’ + Why Cortex β€’ + Quick Start β€’ + Architecture β€’ + Docs +

+ +--- + +## 🎯 What is Cortex? + +Cortex is a **production-ready AI infrastructure stack** built in Rust that handles everything between your application and the AI providers. + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ +β”‚ Your App Cortex AI Providers β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Any │────────────▢│ Rook │───────────▢│ OpenAI β”‚ β”‚ +β”‚ β”‚ SDK β”‚ OpenAI β”‚ Proxy β”‚ β”‚ Anthropic β”‚ β”‚ +β”‚ β”‚ β”‚ Compatibleβ”‚ β”‚ β”‚ Gemini β”‚ β”‚ +β”‚ β”‚ │◀────────────│ + Cache │◀───────────│ Ollama β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ Response β”‚ + Audit β”‚ Fallback β”‚ Groq β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### The Two Products + +| Product | Purpose | What it does | +|---------|---------|--------------| +| **πŸ›‘οΈ Rook** | AI Proxy | Routes requests, handles fallbacks, caches responses, logs everything | +| **πŸ€– Huginn** | Coding Agent | Your local AI coding partner with native tool access | + +--- + +## πŸ“¦ Products + +### πŸ›‘οΈ Rook β€” AI Proxy & Router + +> *"Never let an AI outage break your app again."* + +Rook is an OpenAI-compatible proxy that sits between your app and AI providers. + +``` +Request + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Rook Proxy β”‚ +β”‚ β”‚ +β”‚ 1. Authenticate API key β”‚ +β”‚ 2. Log request (audit) β”‚ +β”‚ 3. Check cache (return if hit) β”‚ +β”‚ 4. Route to primary provider β”‚ +β”‚ β”‚ β”‚ +β”‚ β”œβ”€β”€ Success β†’ Cache β†’ Response β”‚ +β”‚ β”‚ β”‚ +β”‚ └── Failure β†’ Try next provider β”‚ +β”‚ β”‚ β”‚ +β”‚ └── All fail β†’ Error response β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +#### Key Features + +| Feature | Description | +|---------|-------------| +| πŸ”Œ **OpenAI Compatible** | Drop-in replacement for any OpenAI client | +| πŸ”„ **Automatic Fallbacks** | Define combo chains: `gpt-4` β†’ `claude-3` β†’ `gemini-pro` | +| 🏷️ **Model Aliasing** | Use `gpt-4-turbo` β†’ maps to actual model in config | +| ⚑ **Smart Caching** | TTL-based response caching to cut costs | +| πŸ“Š **Full Audit Trail** | Every request/response logged to SQLite | +| πŸ”‘ **API Key Management** | Create, revoke, rotate keys from dashboard | +| πŸš€ **Streaming** | SSE streaming with tool call support | +| 🌐 **Web Dashboard** | Vue 3 SPA embedded in binary | + +#### Providers Supported + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ +β”‚ OpenAI Anthropic Google Gemini β”‚ +β”‚ β”œβ”€ GPT-4o β”œβ”€ Claude 3.5 β”œβ”€ Gemini 1.5 Pro β”‚ +β”‚ β”œβ”€ GPT-4 β”œβ”€ Claude 3 └─ Gemini 1.5 Flash β”‚ +β”‚ └─ GPT-3.5 └─ Claude 2 β”‚ +β”‚ β”‚ +β”‚ Groq Ollama Custom (OpenAI-like) β”‚ +β”‚ β”œβ”€ Llama 3.1 β”œβ”€ Llama 3 β”œβ”€ LM Studio β”‚ +β”‚ └─ Mixtral β”œβ”€ Mistral └─ Local endpoints β”‚ +β”‚ └─ CodeLlama β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +πŸ“– [Docs](docs/rook/README.md) Β· [API Reference](docs/rook/api.md) Β· [Dashboard](apps/rook/dashboard/README.md) Β· [Configuration](docs/rook/configuration.md) + +--- + +### πŸ€– Huginn β€” Local Coding Agent + +> *"Your AI coding partner that respects your privacy."* + +Huginn is a Rust-powered coding assistant that runs locally with access to your codebase. + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ +β”‚ You: "Refactor the auth module to use async/await" β”‚ +β”‚ β”‚ +β”‚ Huginn Processing: β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Parse │────▢│ LLM Call │────▢│ Execute Tools β”‚ β”‚ +β”‚ β”‚ Intent β”‚ β”‚ (Provider) β”‚ β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ +β”‚ β”‚ Read auth/*.rs β”‚ β”‚ +β”‚ β”‚ Edit files β”‚ β”‚ +β”‚ β”‚ Run cargo check β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ Response: Here's the refactored auth module... β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +#### Key Features + +| Feature | Description | +|---------|-------------| +| πŸ’» **Native TUI** | Beautiful terminal interface with Ratatui | +| πŸ”’ **Privacy First** | With local providers, code stays local; remote providers receive prompts and file context | +| πŸ› οΈ **Native Tools** | File ops, terminal, git β€” all built-in | +| πŸ”Œ **MCP Integration** | Connect to any MCP stdio server | +| πŸ’Ύ **Session Memory** | SQLite-backed conversation history | +| πŸ“‹ **Scoped Context** | Per-repo `AGENTS.md` for instructions | + +πŸ“– [Docs](docs/huginn/README.md) Β· [TUI Guide](docs/huginn/README.md#-tui-guide) Β· [MCP Setup](docs/huginn/README.md#-mcp-integration) + +--- + +## ✨ Why Cortex? + +### The Problem + +Building with AI is fragile: + +| Pain Point | Impact | +|------------|--------| +| Provider goes down | Your app breaks | +| Need to switch models | Code changes everywhere | +| Audit requirements | No visibility | +| Cost spikes | Budget surprises | +| Multiple providers | SDK hell | + +### The Solution + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ With Cortex β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ ❌ Provider down? ──▢ βœ… Automatic failover β”‚ +β”‚ ❌ Hard-coded models ──▢ βœ… Model aliases β”‚ +β”‚ ❌ No audit trail ──▢ βœ… Full request logging β”‚ +β”‚ ❌ SDK complexity ──▢ βœ… Single OpenAI-compatible API β”‚ +β”‚ ❌ Cost overruns ──▢ βœ… Response caching β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Performance + +| Metric | Value | +|--------|-------| +| **Response Time** | <5ms overhead (proxy latency) | +| **Cache Hit** | ~50ms (vs 500ms+ API call) | +| **Memory Footprint** | ~20MB (Rook) | +| **Binary Size** | ~15MB (static, musl) | + +--- + +## πŸš€ Quick Start ### Prerequisites -- **Rust 1.89 toolchain** (pinned in `rust-toolchain.toml`; MSRV 1.81 per `Cargo.toml`) -- **Cargo** (included with Rust) -- (Optional) **Just** task runner: `cargo install just` -- (Optional for dashboard) **Node.js** and **pnpm** (`pnpm@11` pinned in root `package.json`) +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Tool β”‚ Version β”‚ Install β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Rust β”‚ 1.81+ β”‚ curl --proto '=https' -sSf \ β”‚ +β”‚ β”‚ β”‚ https://sh.rustup.rs | sh β”‚ +β”‚ Node.js β”‚ 20+ β”‚ nvm install 20 β”‚ +β”‚ pnpm β”‚ latest β”‚ npm i -g pnpm β”‚ +β”‚ Docker β”‚ latest β”‚ docker.com/get-started β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` -### Installation +### Install Rook -#### From source ```bash +# Clone the repo git clone https://github.com/dallay/cortex.git cd cortex + +# Install dashboard dependencies +pnpm install --dir apps/rook/dashboard + +# Build Rook (with embedded dashboard) cargo build --release -p rook + +# Run it +ROOK_CONFIG=./rook.toml cargo run --release -p rook +``` + +### Configure Rook + +```bash +# Create config file +cat > rook.toml << 'EOF' +[server] +host = "127.0.0.1" +port = 3773 + +[cache] +enabled = true +ttl_secs = 3600 +EOF ``` -#### Rust installation from a product tag +> **Note:** Providers are configured via the REST API at `/api/providers` after startup. +> See [Configuration](docs/rook/configuration.md) for full configuration options. + +### Test It + +```bash +# Health check +curl http://localhost:3773/health + +# OpenAI-compatible chat completions (requires API key authentication) +curl http://localhost:3773/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer your-api-key" \ + -d '{ + "model": "gpt-4", + "messages": [{"role": "user", "content": "Hello!"}] + }' + +# Or disable auth for testing (development only): +# Add to rook.toml: +# [auth.api_keys] +# enabled = false +``` -Rook GA supports installing directly from its immutable product tag. Publishing -the internal crates to crates.io is a later distribution phase and is not a -first-release requirement: +### Open Dashboard ```bash -cargo install \ - --git https://github.com/dallay/cortex.git \ - --tag rook@vX.Y.Z \ - --locked \ - -p rook +# Dashboard is embedded at /dashboard/ +# macOS: +open http://localhost:3773/dashboard/ +# Linux: +xdg-open http://localhost:3773/dashboard/ +# Or just copy the URL to your browser + +# Login with admin credentials (set on first run) ``` -#### Binary releases -Download pre-built binaries from [Releases](https://github.com/dallay/cortex/releases) for: -- Linux (x86_64) -- macOS (Intel, Apple Silicon) -- Windows (x86_64) - -Rook and Huginn are separate products with separate versions and release tags. -See the [release and distribution contract](docs/releasing.md) before relying -on a registry or container channel. Huginn's public distribution remains -blocked until its acceptance gates are complete. - -### Quick Start - -1. **Configure Rook**: - Create a config file at `./rook.toml` (or use the `ROOK_CONFIG` env var to point elsewhere): - ```toml - [server] - host = "127.0.0.1" - port = 3773 - - [routing] - strategy = "priority" - - [database] - db_path = "~/.local/share/cortex/rook/rook.db" - ``` - - > Providers are **not** configured in TOML. Create them at runtime via the - > Provider CRUD API (`POST /api/providers`). See the [Configuration Guide](docs/rook/configuration.md). - -2. **Run the server**: - ```bash - # Using cargo - ROOK_CONFIG=./rook.toml cargo run --release -p rook - - # Using binary - ./target/release/rook - ``` - -3. **Test the proxy**: - ```bash - curl http://localhost:3773/v1/chat/completions \ - -H "Content-Type: application/json" \ - -d '{ - "model": "gpt-4", - "messages": [{"role": "user", "content": "Hello!"}] - }' - ``` - - This requires a completion provider configured for Rook; see the - [Configuration Guide](docs/rook/configuration.md) before sending requests. - -## πŸ›  Usage - -### Multi-provider fallback with Combos -Define ordered provider/model fallback steps as `[[combos]]` in `rook.toml` or -through the `/api/combos` CRUD API. Select one per request with -`X-Rook-Combo`, or set `routing.default_combo`. See the -[Configuration Guide](docs/rook/configuration.md#combos-multi-step-fallback-chains) -for the schema and execution behavior. - -### Dashboard access -Rook serves an embedded dashboard at `/dashboard/` on the same port -(e.g. `http://localhost:3773/dashboard/`). For frontend development use -`just run-dashboard` (Vite at `http://localhost:4747/dashboard/`, proxied to the backend). -On a fresh database Rook enters **bootstrap mode** β€” check the logs for the -setup token. See [dashboard README](apps/rook/dashboard/README.md). - -## βš™οΈ Configuration - -See the [Configuration Guide](docs/rook/configuration.md) for detailed options. - -**Quick reference**: -- **Server**: host, port, health check interval. -- **Routing**: strategy (`priority` | `round-robin` | `model-based`), optional `default_combo`. -- **Providers**: managed through `/api/providers`; see the [Provider Management guide](docs/rook/configuration.md#provider-management-dashboard). -- **Combos**: managed via `/api/combos`, selected with `X-Rook-Combo` or `routing.default_combo`. -- **Model aliases**: CRUD at `/api/models/aliases`; global aliases resolve before routing (provider-scoped records are not applied during resolution). -- **Cache / DB / auth / rate limiting**: see full schema in the guide. - -## πŸ— Architecture - -Cortex follows Clean Architecture principles with clear separation of concerns: - -```text +--- + +## πŸ—οΈ Architecture + +### Project Structure + +``` cortex/ -β”œβ”€β”€ apps/rook/ # Binary entry point, DI bootstrap + embedded dashboard -β”œβ”€β”€ apps/huginn/ # Personal Rust coding agent (CLI) +β”‚ +β”œβ”€β”€ apps/ +β”‚ β”œβ”€β”€ rook/ # πŸ›‘οΈ Rook binary +β”‚ β”‚ β”œβ”€β”€ src/ +β”‚ β”‚ β”‚ β”œβ”€β”€ main.rs # Entry point +β”‚ β”‚ β”‚ β”œβ”€β”€ server.rs # Axum server +β”‚ β”‚ β”‚ └── routes/ # HTTP handlers +β”‚ β”‚ └── dashboard/ # πŸ“Š Vue SPA (embedded) +β”‚ β”‚ β”œβ”€β”€ src/views/ # Page components +β”‚ β”‚ β”œβ”€β”€ src/components/ # UI components +β”‚ β”‚ β”œβ”€β”€ src/stores/ # Pinia state +β”‚ β”‚ └── e2e/ # Playwright tests +β”‚ β”‚ +β”‚ └── huginn/ # πŸ€– Huginn binary +β”‚ └── src/ +β”‚ β”œβ”€β”€ crates/ -β”‚ β”œβ”€β”€ domain/ # Business logic -β”‚ β”‚ β”œβ”€β”€ shared-kernel/ # Zero-deps common types -β”‚ β”‚ └── rook-core/ # Domain models, ports, Combo entities -β”‚ β”œβ”€β”€ application/ -β”‚ β”‚ └── rook-usecases/ # Orchestration (RouteRequest, FallbackRouter, CRUD) -β”‚ β”œβ”€β”€ infrastructure/ # External adapters -β”‚ β”‚ β”œβ”€β”€ providers-*/ # LLM clients: openai, anthropic, ollama, gemini, groq (+ core) -β”‚ β”‚ β”œβ”€β”€ provider-sqlite/# Persisted provider connections -β”‚ β”‚ β”œβ”€β”€ combo-sqlite/ # Combo persistence -β”‚ β”‚ β”œβ”€β”€ alias-sqlite/ # Model aliases -β”‚ β”‚ β”œβ”€β”€ auth-sqlite/ # API keys + auth -β”‚ β”‚ β”œβ”€β”€ cache-memory/ # TTL in-memory cache -β”‚ β”‚ β”œβ”€β”€ audit-sqlite/ # Audit logging -β”‚ β”‚ β”œβ”€β”€ db-migration/ # SQLite migrations -β”‚ β”‚ β”œβ”€β”€ models-catalog/ # Model metadata -β”‚ β”‚ β”œβ”€β”€ sse-stream/ # Streaming (SSE) -β”‚ β”‚ β”œβ”€β”€ observability/ # Tracing + metrics -β”‚ β”‚ β”œβ”€β”€ encryption-inmemory/ # Credential encryption boundary -β”‚ β”‚ └── transport-axum/ # HTTP server + OpenAI-compatible adapters -β”‚ β”œβ”€β”€ huginn/ # Huginn core, runtime + Ratatui presentation (no Rook dependency) -β”‚ └── test-support/ # Shared test fixtures -└── docs/ # Documentation +β”‚ β”‚ +β”‚ β”œβ”€β”€ domain/ # πŸ’Ό Business logic (zero deps) +β”‚ β”‚ β”œβ”€β”€ shared-kernel/ # Core types & traits +β”‚ β”‚ └── rook-core/ # Domain models & ports +β”‚ β”‚ +β”‚ β”œβ”€β”€ application/ # 🎻 Use cases +β”‚ β”‚ └── rook-usecases/ # Business rules +β”‚ β”‚ +β”‚ β”œβ”€β”€ infrastructure/ # πŸ”Œ External adapters +β”‚ β”‚ β”œβ”€β”€ providers-openai/ # OpenAI client +β”‚ β”‚ β”œβ”€β”€ providers-anthropic/# Anthropic client +β”‚ β”‚ β”œβ”€β”€ providers-gemini/ # Google Gemini client +β”‚ β”‚ β”œβ”€β”€ providers-ollama/ # Ollama client +β”‚ β”‚ β”œβ”€β”€ providers-groq/ # Groq client +β”‚ β”‚ β”œβ”€β”€ auth-sqlite/ # API key management +β”‚ β”‚ β”œβ”€β”€ audit-sqlite/ # Request logging +β”‚ β”‚ β”œβ”€β”€ cache-memory/ # TTL cache +β”‚ β”‚ └── transport-axum/ # HTTP transport +β”‚ β”‚ +β”‚ └── huginn/ # πŸ€– Huginn runtime +β”‚ └── runtime/ +β”‚ +β”œβ”€β”€ docs/ # πŸ“– Documentation +β”‚ β”œβ”€β”€ rook/ # Rook docs +β”‚ β”‚ β”œβ”€β”€ architecture.md +β”‚ β”‚ β”œβ”€β”€ api.md +β”‚ β”‚ β”œβ”€β”€ configuration.md +β”‚ β”‚ β”œβ”€β”€ providers.md +β”‚ β”‚ └── deployment.md +β”‚ └── huginn/ # Huginn docs +β”‚ +└── dev/ # 🐳 Testing + β”œβ”€β”€ compose.yml # Smoke test + └── compose.e2e.yml # Full E2E ``` -See [Architecture Documentation](docs/rook/architecture.md) for details. +### Tech Stack -## 🧰 Tools +| Layer | Technology | Why | +|-------|------------|-----| +| **Language** | Rust 1.81+ | Memory safety, performance | +| **HTTP Server** | Axum | Ergonomic, async | +| **Runtime** | Tokio | Proven async runtime | +| **Database** | SQLite | Zero-config, portable | +| **Frontend** | Vue 3 + TypeScript | Reactive, typed | +| **Build** | Vite | Fast HMR | +| **TUI** | Ratatui | Native, cross-platform | +| **Testing** | Vitest + Playwright | Fast + E2E | -| Tool | Status | Description | -|------|--------|-------------| -| [Rook](apps/rook/) | βœ… Active | AI proxy/router with multi-provider support | -| [Huginn](docs/huginn/README.md) | 🚧 Personal MVP in progress | Local Rust coding agent: CLI + Ratatui TUI, streaming, native tools, SQLite sessions, MCP stdio | -| *Future tools* | 🚧 Planned | TBD | +--- -## πŸ›  Development +## πŸ› οΈ Development ### Setup + ```bash -# Clone and setup -git clone https://github.com/dallay/cortex.git -cd cortex +# Install dependencies just setup ``` -### Development commands +### Common Commands + ```bash -# Format code +# Format, lint, test just fmt - -# Run linter just clippy - -# Run tests just test -# Watch mode (auto-check, test, clippy) -just dev +# Run locally +just run # Rook server +just run-dashboard # Vite dev server +just huginn-run # Huginn + +# E2E testing +just test-e2e # Full E2E suite +just dev-up # Smoke test container # Full CI locally just ci-local ``` -### Testing -```bash -# Run all tests -cargo test --workspace +### Code Quality -# Run specific crate tests -cargo test -p rook-core +```bash +# Rust only +cargo fmt --all +cargo clippy --all -- -D warnings -# Run E2E tests (requires Docker) -just test-e2e +# Dashboard only +cd apps/rook/dashboard +pnpm typecheck && pnpm build && pnpm exec vitest run ``` +πŸ“– [Development Guide](docs/development.md) Β· [Testing Guide](dev/README.md) Β· [Contributing](CONTRIBUTING.md) + +--- + ## πŸ“š Documentation -- [Architecture](docs/rook/architecture.md) -- [Configuration](docs/rook/configuration.md) (providers via CRUD API, combos, aliases) -- [Providers](docs/rook/providers.md) -- [API Reference](docs/rook/api.md) -- [Deployment](docs/rook/deployment.md) -- [Release and distribution contract](docs/releasing.md) -- [ADR-0015: Product releases versus Cargo publishing](docs/huginn/adr/0015-separate-product-releases-from-cargo-publishing.md) -- [API key troubleshooting](docs/api-key-troubleshooting.md) -- [Rook dashboard](apps/rook/dashboard/README.md) (Vue SPA, embedded at `/dashboard/`) -- [Local Docker testing](dev/README.md) (smoke, Playwright E2E, multi-distro) -- [Huginn coding agent](docs/huginn/README.md) +| Guide | Description | +|-------|-------------| +| [Rook Architecture](docs/rook/architecture.md) | How Rook works internally | +| [API Reference](docs/rook/api.md) | All HTTP endpoints | +| [Configuration](docs/rook/configuration.md) | Complete config reference | +| [Providers](docs/rook/providers.md) | Provider setup & quirks | +| [Deployment](docs/rook/deployment.md) | Production deployment | +| [Huginn Docs](docs/huginn/README.md) | Coding agent documentation | +| [Dev Testing](dev/README.md) | Local testing with Docker | -## πŸ—Ί Roadmap +--- -Project priorities evolve with active development. See the [GitHub issue -tracker](https://github.com/dallay/cortex/issues) for current work and planned -features rather than relying on a static roadmap in this README. +## πŸ“Š Project Stats + +
+ +| Metric | Value | +|--------|-------| +| πŸ¦€ **Rust Version** | 1.81+ (MSRV) | +| πŸ“¦ **Crates** | 15+ packages | +| 🌐 **Providers** | 5 (OpenAI, Anthropic, Gemini, Ollama, Groq) | +| πŸ“„ **License** | MIT | +| ⭐ **Stars** | [GitHub](https://github.com/dallay/cortex/stargazers) | + +
+ +--- ## 🀝 Contributing -We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details. +We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for: + +- Development setup +- Code style guidelines +- Pull request process +- Issue templates -Follow the [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct). +We follow the [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct). + +--- ## πŸ“„ License -This project is licensed under the [MIT License](LICENSE). +MIT License. See [LICENSE](LICENSE). + +--- ## πŸ‘₯ Community -- πŸ’¬ [GitHub Discussions](https://github.com/dallay/cortex/discussions) - Questions and ideas -- πŸ› [Issue Tracker](https://github.com/dallay/cortex/issues) - Bug reports and feature requests +| Channel | Purpose | +|---------|---------| +| πŸ’¬ [Discussions](https://github.com/dallay/cortex/discussions) | Questions & ideas | +| πŸ› [Issues](https://github.com/dallay/cortex/issues) | Bug reports | +| 🌐 [DeepWiki](https://deepwiki.com/dallay/cortex) | AI-powered docs | -## πŸ™ Acknowledgments +--- -Built with: -- [Rust](https://www.rust-lang.org/) - Systems programming language -- [Tokio](https://tokio.rs/) - Async runtime -- [Axum](https://github.com/tokio-rs/axum) - Web framework -- [Rusqlite](https://github.com/rusqlite/rusqlite) - SQLite bindings +
-Special thanks to all contributors and the Rust community. +**Built with Rust** Β· **Designed for Production** Β· **Ready for Your AI Stack** + +
diff --git a/apps/rook/README.md b/apps/rook/README.md new file mode 100644 index 00000000..a997c7c6 --- /dev/null +++ b/apps/rook/README.md @@ -0,0 +1,339 @@ +
+ +# πŸ›‘οΈ Rook + +AI Proxy & Router β€” The Core Binary + +[![Rust](https://img.shields.io/badge/rust-1.81%2B-DEA584?logo=rust&labelColor=4A4A4A)](https://www.rust-lang.org) +[![Axum](https://img.shields.io/badge/axum-0.7-8B5CF6?logo=tokio)](https://github.com/tokio-rs/axum) +[![SQLite](https://img.shields.io/badge/sqlite-3-003B57?logo=sqlite)](https://www.sqlite.org) +[![License](https://img.shields.io/github/license/dallay/cortex)](https://github.com/dallay/cortex/blob/main/LICENSE) + +The production binary that runs the Rook AI proxy server with embedded dashboard. + +[Overview](#-overview) Β· [Quick Start](#-quick-start) Β· [CLI Reference](#-cli-reference) Β· [Configuration](#-configuration) Β· [Dashboard](#-dashboard) + +
+ +--- + +## 🎯 Overview + +Rook is the **AI proxy binary** that powers Cortex. It provides: + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Rook Server β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ HTTP API (port 3773) β”‚ +β”‚ β”œβ”€β”€ /health β†’ Health check β”‚ +β”‚ β”œβ”€β”€ /v1/chat/* β†’ OpenAI-compatible chat completions β”‚ +β”‚ β”œβ”€β”€ /api/* β†’ Management API β”‚ +β”‚ └── /dashboard/* β†’ Embedded Vue SPA β”‚ +β”‚ β”‚ +β”‚ Core Features β”‚ +β”‚ β”œβ”€β”€ πŸ” Authentication β†’ API key validation β”‚ +β”‚ β”œβ”€β”€ πŸ”„ Routing β†’ Provider fallback chains β”‚ +β”‚ β”œβ”€β”€ ⚑ Caching β†’ TTL-based response cache β”‚ +β”‚ β”œβ”€β”€ πŸ“Š Audit β†’ Request/response logging β”‚ +β”‚ └── 🏷️ Aliasing β†’ Model name mapping β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Components + +| Component | Description | +|-----------|-------------| +| **HTTP Server** | Axum-based server with OpenAI-compatible API | +| **Dashboard** | Vue 3 SPA embedded at build time | +| **Providers** | OpenAI, Anthropic, Gemini, Ollama, Groq | +| **Storage** | SQLite for auth, audit logs, and provider configs | +| **Cache** | In-memory TTL cache for responses | + +--- + +## πŸš€ Quick Start + +### Build + +```bash +# From repository root +cargo build --release -p rook + +# Or with embedded dashboard +cargo build --release -p rook +``` + +### Run + +```bash +# Basic run (no config file) +cargo run --release -p rook + +# With config file +ROOK_CONFIG=./rook.toml cargo run --release -p rook +``` + +### First-Time Setup + +```bash +# 1. Start Rook +ROOK_CONFIG=./rook.toml cargo run --release -p rook + +# 2. Access dashboard at http://localhost:3773/dashboard/ + +# 3. Login with default admin credentials (set on first run via terminal prompt) + +# 4. Configure providers via dashboard or API +# POST /api/providers +``` + +--- + +## πŸ“– CLI Reference + +```bash +rook [OPTIONS] +``` + +### Options + +| Flag | Default | Description | +|------|---------|-------------| +| `--host` | `127.0.0.1` | Server bind address | +| `--port` | `3773` | Server port | +| `--config` | β€” | Path to config TOML file | +| `--help` | β€” | Show help | +| `--version` | β€” | Show version | + +### Environment Variables + +| Variable | Description | +|----------|-------------| +| `ROOK_CONFIG` | Path to configuration file | +| `ROOK_HOST` | Override host | +| `ROOK_PORT` | Override port | +| `RUST_LOG` | Log level (trace, debug, info, warn, error) | + +### Examples + +```bash +# Development with verbose logging +RUST_LOG=debug cargo run --release -p rook + +# Production with custom port +rook --port 8080 --config /etc/rook.toml + +# Using environment variables +ROOK_HOST=0.0.0.0 ROOK_PORT=3773 rook +``` + +--- + +## βš™οΈ Configuration + +### Config File (TOML) + +```toml +[server] +host = "127.0.0.1" +port = 3773 + +[cache] +enabled = true +ttl_secs = 3600 + +[audit] +enabled = true + +[auth] +enabled = true +``` + +### Full Schema + +| Section | Key | Type | Default | Description | +|---------|-----|------|---------|-------------| +| `server` | `host` | string | `"127.0.0.1"` | Bind address | +| `server` | `port` | integer | `3773` | Server port | +| `cache` | `enabled` | boolean | `true` | Enable response caching | +| `cache` | `ttl_secs` | integer | `3600` | Cache TTL in seconds | +| `audit` | `enabled` | boolean | `true` | Enable audit logging | +| `auth` | `enabled` | boolean | `true` | Require API key auth | + +> **Note:** Provider configuration is done via the REST API at `/api/providers` after startup. +> See [Configuration Docs](docs/rook/configuration.md) for detailed options. + +--- + +## πŸ“Š Dashboard + +The Vue 3 dashboard is **embedded in the binary** at build time. + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Rook Dashboard (embedded) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ http://localhost:3773/dashboard/ β”‚ +β”‚ β”‚ +β”‚ Pages: β”‚ +β”‚ β”œβ”€β”€ /dashboard/ β†’ Home / Overview β”‚ +β”‚ β”œβ”€β”€ /dashboard/providers β†’ Manage providers β”‚ +β”‚ β”œβ”€β”€ /dashboard/api-keys β†’ API key management β”‚ +β”‚ β”œβ”€β”€ /dashboard/combos β†’ Fallback chains β”‚ +β”‚ β”œβ”€β”€ /dashboard/audit β†’ Audit logs β”‚ +β”‚ └── /dashboard/settings β†’ Server settings β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Development Mode + +For dashboard development without full rebuilds: + +```bash +# Terminal 1: Run Rook backend +just run + +# Terminal 2: Run Vite dev server +just run-dashboard + +# Access at http://localhost:4747/dashboard/ +# (Vite proxies API requests to Rook on port 3773) +``` + +--- + +## πŸ—οΈ Project Structure + +``` +apps/rook/ +β”œβ”€β”€ src/ +β”‚ └── main.rs # Entry point, CLI parsing, server setup +β”œβ”€β”€ dashboard/ # Vue 3 SPA (embedded in binary) +β”‚ β”œβ”€β”€ src/ +β”‚ β”‚ β”œβ”€β”€ views/ # Page components +β”‚ β”‚ β”œβ”€β”€ components/ # UI components +β”‚ β”‚ β”œβ”€β”€ stores/ # Pinia state +β”‚ β”‚ β”œβ”€β”€ lib/ # API client +β”‚ β”‚ └── locales/ # i18n (en, es) +β”‚ └── e2e/ # Playwright tests +β”œβ”€β”€ tests/ # Integration tests +β”œβ”€β”€ Dockerfile # Production container +β”œβ”€β”€ build.rs # Build script (embeds dashboard) +└── Cargo.toml # Dependencies +``` + +--- + +## 🐳 Docker + +### Build Image + +```bash +# From repository root +docker build -f apps/rook/Dockerfile -t rook:latest . +``` + +### Run Container + +```bash +docker run -d \ + --name rook \ + -p 3773:3773 \ + -v ./rook.toml:/app/rook.toml \ + -e ROOK_CONFIG=/app/rook.toml \ + rook:latest +``` + +### Docker Compose + +```yaml +services: + rook: + build: . + ports: + - "3773:3773" + volumes: + - ./rook.toml:/app/rook.toml + environment: + - ROOK_CONFIG=/app/rook.toml + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3773/health"] + interval: 30s + timeout: 10s + retries: 3 +``` + +--- + +## πŸ§ͺ Testing + +```bash +# Unit tests +cargo test -p rook + +# Integration tests +cargo test --test '*' -p rook + +# With coverage +cargo tarpaulin -p rook --out Html +``` + +### E2E Tests + +```bash +# Build E2E image +just test-e2e-build + +# Run E2E suite +just test-e2e +``` + +--- + +## πŸ“š Documentation + +| Resource | Description | +|----------|-------------| +| [Rook Docs](docs/rook/README.md) | Full Rook documentation | +| [API Reference](docs/rook/api.md) | HTTP endpoints | +| [Configuration](docs/rook/configuration.md) | Config options | +| [Providers](docs/rook/providers.md) | Provider setup | +| [Dashboard](apps/rook/dashboard/README.md) | Dashboard development | +| [Architecture](docs/rook/architecture.md) | Internal design | + +--- + +## πŸ”§ Development + +```bash +# Watch mode (requires cargo-watch) +cargo watch -x build -p rook + +# Run with debug logging +RUST_LOG=debug cargo run -p rook + +# Check formatting +cargo fmt -p rook + +# Lint +cargo clippy -p rook -- -D warnings +``` + +--- + +## πŸ“„ License + +MIT License - same as [Cortex repository](https://github.com/dallay/cortex). + +--- + +
+ +**Built with Rust** Β· **Axum** Β· **SQLite** Β· **Vue 3** + +
diff --git a/apps/rook/dashboard/README.md b/apps/rook/dashboard/README.md index ea27e7bc..e3c0c4cc 100644 --- a/apps/rook/dashboard/README.md +++ b/apps/rook/dashboard/README.md @@ -1,63 +1,297 @@ -# Rook Dashboard +
-The Rook management dashboard is a Vue 3 SPA, embedded in the production Rook -binary under `/dashboard/`. Vite serves it on port `4747` and proxies API requests -to the backend on port `3773` by default. +# πŸ“Š Rook Dashboard -## Requirements +Vue 3 Management Interface for Rook AI Proxy -- Node.js and pnpm (version pinned in the root `package.json`) -- A running Rook backend for authenticated management flows and API data +[![Vue](https://img.shields.io/badge/vue-3.4-4FC08D?logo=vuedotjs)](https://vuejs.org) +[![TypeScript](https://img.shields.io/badge/typescript-5.0-3178C6?logo=typescript)](https://www.typescriptlang.org) +[![Vite](https://img.shields.io/badge/vite-5.0-646CFF?logo=vite)](https://vitejs.dev) +[![Vitest](https://img.shields.io/badge/vitest-2.0-6E9F18?logo=vitest)](https://vitest.dev) +[![Playwright](https://img.shields.io/badge/playwright-1.40-2EAD33?logo=playwright)](https://playwright.dev) +[![pnpm](https://img.shields.io/badge/pnpm-C867F2?logo=pnpm)](https://pnpm.io) +[![License](https://img.shields.io/github/license/dallay/cortex)](https://github.com/dallay/cortex/blob/main/LICENSE) -Install workspace dependencies with `pnpm install` from the repository root. +
-## Local development +--- -Start Rook, then start Vite from the repository root: +## 🎯 What is the Dashboard? + +The Rook Dashboard is a **Vue 3 SPA** that provides a visual interface for managing your Rook AI Proxy instance. + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Rook Dashboard Architecture β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ Browser (localhost:4747) β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ Vue 3 SPA β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Views β”‚ Components β”‚ β”‚ +β”‚ β”‚ ───────────────────── β”‚ ───────────────────── β”‚ β”‚ +β”‚ β”‚ β€’ Login β”‚ β€’ ProviderCard β”‚ β”‚ +β”‚ β”‚ β€’ Dashboard β”‚ β€’ ApiKeyTable β”‚ β”‚ +β”‚ β”‚ β€’ Providers β”‚ β€’ ComboEditor β”‚ β”‚ +β”‚ β”‚ β€’ API Keys β”‚ β€’ AuditLog β”‚ β”‚ +β”‚ β”‚ β€’ Settings β”‚ β€’ ChatInterface β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ Vite Proxy (/api/* β†’ port 3773) β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Rook Backend (port 3773) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Features + +| Feature | Description | +|---------|-------------| +| πŸ” **Authentication** | Secure login with Rook's admin credentials | +| 🌍 **Provider Management** | Configure OpenAI, Anthropic, Gemini, Ollama, Groq | +| πŸ”‘ **API Key CRUD** | Create, view, and revoke API keys | +| πŸ”„ **Combo Editor** | Visual builder for fallback chains | +| πŸ“Š **Audit Logs** | Searchable request/response history | +| πŸ’¬ **Chat Interface** | Test requests directly in the browser | +| 🌐 **i18n** | English and Spanish translations | + +--- + +## πŸš€ Quick Start + +### Prerequisites + +| Requirement | Version | +|-------------|---------| +| Node.js | 20+ | +| pnpm | latest | +| Running Rook backend | port 3773 | + +### Setup ```bash +# Install dependencies (from repo root) +pnpm install + +# Or from this directory +cd apps/rook/dashboard +pnpm install +``` + +### Development + +```bash +# Option 1: Using just (recommended) just run-dashboard + +# Option 2: Manual +cd apps/rook/dashboard +pnpm dev ``` -Open . The dev server proxies `/api/`, -`/health`, and authentication requests to `http://127.0.0.1:3773`. +Then open [http://localhost:4747/dashboard/](http://localhost:4747/dashboard/) + +The dev server automatically proxies: +- `/api/*` β†’ `http://127.0.0.1:3773` +- `/health` β†’ `http://127.0.0.1:3773` -To use another backend or base path, set `API_TARGET` or `BASE_PATH` when running -Vite. For example: +### Custom Configuration ```bash -cd apps/rook/dashboard +# Different backend URL API_TARGET=http://127.0.0.1:8081 pnpm dev + +# Custom base path +BASE_PATH=/custom-path pnpm dev +``` + +--- + +## πŸ“ Project Structure + +``` +apps/rook/dashboard/ +β”œβ”€β”€ src/ +β”‚ β”œβ”€β”€ views/ # πŸ“„ Page components +β”‚ β”‚ β”œβ”€β”€ LoginView.vue +β”‚ β”‚ β”œβ”€β”€ HomeView.vue +β”‚ β”‚ β”œβ”€β”€ ProvidersView.vue +β”‚ β”‚ β”œβ”€β”€ ApiKeysView.vue +β”‚ β”‚ └── SettingsView.vue +β”‚ β”‚ +β”‚ β”œβ”€β”€ components/ # 🧩 Reusable UI components +β”‚ β”‚ β”œβ”€β”€ common/ # Buttons, inputs, cards +β”‚ β”‚ β”œβ”€β”€ providers/ # Provider-specific components +β”‚ β”‚ β”œβ”€β”€ api-keys/ # API key management +β”‚ β”‚ └── audit/ # Audit log components +β”‚ β”‚ +β”‚ β”œβ”€β”€ stores/ # πŸ“¦ Pinia state management +β”‚ β”‚ β”œβ”€β”€ auth.ts +β”‚ β”‚ β”œβ”€β”€ providers.ts +β”‚ β”‚ └── audit.ts +β”‚ β”‚ +β”‚ β”œβ”€β”€ router/ # πŸ›€οΈ Vue Router configuration +β”‚ β”‚ └── index.ts +β”‚ β”‚ +β”‚ β”œβ”€β”€ locales/ # 🌐 i18n translations +β”‚ β”‚ β”œβ”€β”€ en.json +β”‚ β”‚ └── es.json +β”‚ β”‚ +β”‚ β”œβ”€β”€ lib/ # πŸ”Œ Backend API client +β”‚ β”‚ └── api.ts +β”‚ β”‚ +β”‚ └── App.vue # Root component +β”‚ +β”œβ”€β”€ e2e/ # πŸ§ͺ Playwright E2E tests +β”‚ β”œβ”€β”€ login.spec.ts +β”‚ β”œβ”€β”€ providers.spec.ts +β”‚ β”œβ”€β”€ api-keys.spec.ts +β”‚ └── vue.spec.ts +β”‚ +β”œβ”€β”€ vite.config.ts # ⚑ Vite configuration +β”œβ”€β”€ playwright.config.ts # 🎭 Playwright configuration +β”œβ”€β”€ tsconfig.json # πŸ“˜ TypeScript config +└── package.json # πŸ“¦ Dependencies ``` -## Checks +--- -From `apps/rook/dashboard/`, run: +## πŸ§ͺ Testing + +### Unit Tests ```bash -pnpm typecheck && pnpm build && pnpm exec vitest run +cd apps/rook/dashboard + +# Run all tests +pnpm exec vitest run + +# Watch mode +pnpm exec vitest + +# With coverage +pnpm exec vitest run --coverage ``` -`just ci-local` runs the dashboard checks as part of the workspace quality gate. +### Type Checking -## End-to-end tests +```bash +pnpm typecheck +``` -Playwright tests in `e2e/` cover login, providers, API keys, and dashboard flows. -The Docker-backed workflow prepares the backend, admin account, and dashboard: +### Build ```bash +pnpm build +``` + +### End-to-End Tests + +E2E tests require Docker and a running Rook backend: + +```bash +# Full E2E suite just test-e2e + +# Manual run +just test-e2e-build # Build Docker image +just test-e2e # Run tests +``` + +πŸ“– [E2E Testing Guide](../../../dev/README.md#path-2--playwright-e2e-against-docker) + +### Quality Gate + +```bash +# Run all checks (CI simulation) +just ci-local ``` -See the [dev test guide](../../../dev/README.md#path-2--playwright-e2e-against-docker) -for manual runs and browser installation. +--- + +## 🎨 Development + +### Type Check + +```bash +pnpm typecheck +``` + +### Adding a New View + +```typescript +// src/views/NewFeatureView.vue + + + +``` + +### Adding a Component + +```typescript +// src/components/common/MyButton.vue + + + +``` + +--- + +## πŸ”§ Environment Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `API_TARGET` | `http://127.0.0.1:3773` | Rook backend URL | +| `BASE_PATH` | `/dashboard` | Application base path | +| `VITE_APP_TITLE` | `Rook Dashboard` | Browser tab title | + +--- + +## πŸ“š Documentation + +| Resource | Description | +|----------|-------------| +| [Rook Docs](docs/rook/README.md) | Rook proxy documentation | +| [API Reference](docs/rook/api.md) | Backend API endpoints | +| [Configuration](docs/rook/configuration.md) | Rook config options | +| [Dev Guide](dev/README.md) | Local testing with Docker | + +--- + +## 🀝 Contributing + +See [Contributing Guide](CONTRIBUTING.md) in the repository root. + +--- + +## πŸ“„ License + +MIT License - same as [Cortex repository](https://github.com/dallay/cortex). + +--- -## Structure and configuration +
-Pages live in `src/views/`, shared UI in `src/components/`, routing in -`src/router/`, Pinia state in `src/stores/`, and English/Spanish translations in -`src/locales/`. `vite.config.ts` defines the base path and proxy; `playwright.config.ts` -defines browser projects and E2E settings. +**Vue 3** Β· **TypeScript** Β· **Pinia** Β· **Vue Router** Β· **i18n** -See the [Rook configuration guide](../../../docs/rook/configuration.md), [API reference](../../../docs/rook/api.md), -and [workspace README](../../../README.md) for backend setup and product context. +
diff --git a/dev/README.md b/dev/README.md index 8f21cb84..e32f03fe 100644 --- a/dev/README.md +++ b/dev/README.md @@ -1,199 +1,339 @@ -# dev/ β€” Local Testing Without Host Pollution +
-Three isolated paths depending on what you need to test. -Nothing writes to your host OS beyond Docker images and mapped ports. +# 🐳 Dev Testing Guide + +Local testing without host pollution + +[![Docker](https://img.shields.io/badge/docker-ready-2496ED?logo=docker)](https://www.docker.com) +[![Platform](https://img.shields.io/badge/platform-linux%20%7C%20macOS-808080?logo=linux)](https://www.linux.org) +[![Bash](https://img.shields.io/badge/bash-5.0-4EAA25?logo=gnubash)](https://www.gnu.org/software/bash/) +[![License](https://img.shields.io/github/license/dallay/cortex)](https://github.com/dallay/cortex/blob/main/LICENSE) + +**Three isolated paths** β€” nothing writes to your host OS beyond Docker images and mapped ports. + +[🐚 Just Recipes](#path-1--smoke-test-container) Β· [🎭 Playwright E2E](#path-2--playwright-e2e-against-docker) Β· [πŸ“¦ Multi-distro](#path-3--multi-distro-e2e) + +
--- -## Which path do I use? +## 🎯 Which Path Do I Use? + +| Goal | Path | Speed | +|------|------|-------| +| Verify backend starts and `/health` responds | [Path 1 β€” Smoke Test](#path-1--smoke-test-container) | ⚑ Fast (~2 min) | +| Full E2E (dashboard + API key CRUD) | [Path 2 β€” Playwright E2E](#path-2--playwright-e2e-against-docker) | 🐒 Slow (~10 min) | +| Binary validation (Ubuntu + Alpine) | [Path 3 β€” Multi-distro](#path-3--multi-distro-e2e) | 🐒 Slow (~15 min) | -| Goal | Path | -|------|------| -| Verify the backend starts and `/health` responds | [Path 1 β€” Smoke test container](#path-1--smoke-test-container) | -| Full Playwright E2E (dashboard + API key CRUD) against Docker | [Path 2 β€” Playwright E2E against Docker](#path-2--playwright-e2e-against-docker) | -| Multi-distro binary validation (Ubuntu + Alpine) | [Path 3 β€” Multi-distro E2E](#path-3--multi-distro-e2e) | +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Testing Architecture β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Your Host β”‚ β”‚ +β”‚ β”‚ (macOS) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ just dev-* β”‚ +β”‚ β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Docker Container β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ Path 1: rook β”‚ β”‚ Path 2: full β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ (debug, no UI) β”‚ β”‚ (debug + admin) β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ Path 3: alpine β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ (musl binary) β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Ports: 8090 β†’ 3773 (host β†’ container) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` --- -## Path 1 β€” Smoke test container +## Path 1 β€” Smoke Test Container + +**Fastest path.** Builds Rook in debug mode (no dashboard) and confirms the API layer works. -Fastest path. Builds rook in **debug mode** (no dashboard) and confirms the API -layer works. Use this when you only need to verify the backend, health check, or -API routing without any UI. +### What You Get -**Port**: `8090` on host β†’ `3773` in container -**Database**: in-memory (`:memory:`) β€” ephemeral, clean slate on every restart -**Dashboard**: NOT available (Vue SPA is not built in debug mode β†’ `/dashboard` returns 404) +| Feature | Available | +|---------|-----------| +| Backend API | βœ… On port 8090 | +| Health check | βœ… `curl localhost:8090/health` | +| Database | βœ… In-memory (`:memory:`) | +| Dashboard | ❌ Not built in debug mode | +| Logs | βœ… `just dev-logs` | + +### Commands ```bash # Build the image (first time or after code changes) -just dev-build # or: dev/run.sh build +just dev-build # Start container and wait until /health is OK -just dev-up # or: dev/run.sh up +just dev-up # Verify curl http://127.0.0.1:8090/health # Tail logs -just dev-logs # or: dev/run.sh logs +just dev-logs # Shell into container -just dev-shell # or: dev/run.sh shell +just dev-shell -# Stop and remove -just dev-down # or: dev/run.sh down +# Stop and remove container +just dev-down # Remove image + container -just dev-clean # or: dev/run.sh clean +just dev-clean ``` -> **macOS + OrbStack note**: use `127.0.0.1` instead of `localhost` to avoid -> IPv6-first resolution quirks where OrbStack only binds the IPv4 port. +### Config -### Config used +Use `dev/config.toml` to override defaults: -`dev/test-configs/rook-dev.toml` β€” in-memory DB, cache disabled, no provider CRUD. +```toml +[server] +host = "0.0.0.0" +port = 3773 +``` -### Limitations (intentional) +### Troubleshooting -- Debug build β†’ much faster image builds (Cargo cache hits), but no embedded Vue SPA. -- `provider_crud.enabled = false` β†’ Provider CRUD endpoints are not mounted. -- No auth API keys enabled β†’ all requests are unauthenticated. +> **macOS + OrbStack note:** Use `127.0.0.1` instead of `localhost` to avoid +> IPv6-first resolution quirks where OrbStack only binds the IPv4 port. --- -## Path 2 β€” Playwright E2E against Docker +## Path 2 β€” Playwright E2E Against Docker + +**Full E2E suite.** Tests the dashboard login, provider management, API key CRUD, and dashboard flows. -Full-stack E2E: backend runs in Docker (isolated DB on disk inside container), -dashboard runs locally via `pnpm dev`, Playwright drives Chromium + Firefox + WebKit. +### What You Get -**Port**: `3773` on host β†’ `3773` in container -**Database**: `/tmp/rook-e2e.db` inside the container (tmpfs-backed, gone when container is removed) -**Dashboard**: `http://localhost:4747/dashboard/` (Vite dev server on your machine) -**Admin password**: `Admin123456-` (seeded automatically via `rook seed-admin`) +| Feature | Available | +|---------|-----------| +| Backend API | βœ… Running in `rook:e2e-api-keys` container | +| Admin account | βœ… `admin@rook.local` / `rook-admin-123` | +| Dashboard | βœ… Built and served | +| Audit data | βœ… In-memory (ephemeral) | +| Database | βœ… SQLite at `/tmp/rook-e2e.db` (container tmpfs) | +| E2E tests | βœ… Playwright | -### Prerequisites +### Architecture -- Docker running -- `pnpm install` done in `apps/rook/dashboard` (run `just dashboard-install` if not) -- Playwright browsers installed (`cd apps/rook/dashboard && npx playwright install`) +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ E2E Test Architecture β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Docker Compose β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ rook:latest β”‚ β”‚ postgres:16 β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ (release) β”‚ β”‚ (audit logs) β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Port: 3773 β”‚ Port: 5432 β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Playwright (host) β”‚ β”‚ β”‚ +β”‚ β”‚ β–Ό β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ Browser (Chromium/Firefox/Webkit) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Tests: login, providers, api-keys, dashboard β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` -### Run tests automatically +### Commands ```bash -# Build image + start container + start dashboard + run all Playwright tests + cleanup +# Build the E2E Docker image +just test-e2e-build + +# Run E2E tests just test-e2e -# or directly: -dev/e2e/run-api-keys-e2e.sh --test + +# Run specific test file +cd apps/rook/dashboard +pnpm exec playwright test e2e/login.spec.ts + +# Run with UI (headed mode) +pnpm exec playwright test --headed + +# Debug mode +pnpm exec playwright test --debug ``` -This does everything in one shot: -1. Builds `rook:e2e-api-keys` from `Dockerfile.dev` (repo root) -2. Starts the container on port `3773` -3. Seeds the admin account inside the container -4. Starts `pnpm dev` for the dashboard in the background -5. Runs `playwright test e2e/api-keys.spec.ts` -6. Cleans up container and dashboard process +### Manual Run -### Manual testing mode +```bash +# Use just recipes for E2E workflow +just test-e2e # Run full E2E suite +just test-e2e-dev # Development mode with watch +just test-e2e-cleanup # Clean up containers and volumes +``` -Start the container and leave it running so you can interact with the dashboard -in a browser or run individual Playwright tests by hand. +For integration testing with `docker-compose.test.yml`: ```bash -# Start container only (no tests, stays running) -just test-e2e-dev -# or: dev/e2e/run-api-keys-e2e.sh +# 1. Start Docker Compose +docker compose -f docker-compose.test.yml up -d -# In a second terminal β€” start the dashboard -just run-dashboard # http://localhost:4747/dashboard/ +# 2. Wait for services +sleep 10 -# In a third terminal β€” run specific tests +# 3. Run tests cd apps/rook/dashboard -pnpm playwright test e2e/api-keys.spec.ts --project=chromium -pnpm playwright test e2e/api-keys.spec.ts --debug +pnpm exec playwright test -# When done β€” stop and remove the container -just test-e2e-cleanup -# or: dev/e2e/run-api-keys-e2e.sh --cleanup +# 4. Cleanup +docker compose -f docker-compose.test.yml down -v ``` -Log in at `http://localhost:4747/dashboard/` with: -- **Email**: `admin@rook.local` -- **Password**: `Admin123456-` - -### Config used - -`dev/test-configs/rook-api-keys-test.toml` β€” auth API keys enabled, provider CRUD enabled, -cache disabled, DB at `/tmp/rook-e2e.db` (inside container). +### Test Coverage -### Dockerfile used - -`Dockerfile.dev` at the **repo root** (not `dev/Dockerfile.dev`). -This image includes the dashboard build embedded in the Rook binary. +| Test File | Coverage | +|-----------|----------| +| `e2e/login.spec.ts` | Login flow, logout, session persistence | +| `e2e/providers.spec.ts` | Provider CRUD, connection testing | +| `e2e/api-keys.spec.ts` | API key creation, revocation, listing | +| `e2e/vue.spec.ts` | Navigation, settings, audit logs | --- ## Path 3 β€” Multi-distro E2E -Validates the rook binary runs correctly on Ubuntu (Debian Bookworm) and Alpine. -Useful before a release or when changing system dependencies. +**Binary validation.** Tests the release binary on Ubuntu and Alpine to ensure musl compatibility. -**Ports**: `8081` (ubuntu), `8082` (alpine) on host +### What You Get -```bash -# Build images for both distros -dev/e2e-test.sh build +| Feature | Available | +|---------|-----------| +| Ubuntu 22.04 | βœ… amd64 | +| Alpine 3.19 | βœ… amd64 (musl) | +| rook binary | βœ… Release build | +| Health check | βœ… Cross-distro | -# Start both containers -dev/e2e-test.sh up +### Commands -# Run smoke tests against all distros +```bash +# Build release binary +just build + +# Run multi-distro tests dev/e2e-test.sh test -# Test a single distro +# Run only Ubuntu dev/e2e-test.sh test ubuntu + +# Run only Alpine dev/e2e-test.sh test alpine +``` + +--- + +## πŸ› οΈ Just Recipes Reference + +| Recipe | Description | +|--------|-------------| +| `just dev-build` | Build dev Docker image | +| `just dev-up` | Start smoke test container | +| `just dev-down` | Stop container | +| `just dev-logs` | Tail container logs | +| `just dev-shell` | Shell into container | +| `just dev-clean` | Remove image + container | +| `just test-e2e-build` | Build E2E Docker image | +| `just test-e2e` | Run full E2E suite | +| `just test-e2e-dev` | Development mode with manual testing | +| `just test-e2e-cleanup` | Stop/remove E2E containers | +| `just build` | Build release binary | +| `just build-app` | Build rook binary only | + +Full list: `just --list` + +--- + +## πŸ”§ Troubleshooting -# Check /health on a distro -dev/e2e-test.sh health ubuntu +### Container won't start -# Shell into a container -dev/e2e-test.sh shell ubuntu +```bash +# Check Docker is running +docker info -# Stop everything -dev/e2e-test.sh down +# View container logs +docker compose -f dev/compose.yml logs -# Remove images + containers -dev/e2e-test.sh clean +# Rebuild from scratch +just dev-clean && just dev-build ``` -### What the distro tests cover +### Tests fail with timeout -| Check | Description | -|-------|-------------| -| `/health` | Returns valid JSON with `status` + `providers` | -| Empty registry | `no_providers_configured` error β€” no panics | -| CRUD β†’ routing | Create provider β†’ refresh β†’ route request (manual step) | +```bash +# Increase timeout in compose +TIMEOUT=60 just test-e2e +``` + +### Port already in use + +```bash +# Kill process on port 8090 +lsof -ti:8090 | xargs kill -9 + +# The smoke workflow uses port 8090 on host β†’ 3773 in container +# See dev/run.sh and dev/docker-compose.dev.yml for details +just dev-up +``` + +### Alpine tests fail (musl issues) + +```bash +# Check binary architecture +file target/release/rook + +# Verify musl linking +ldd target/release/rook # Should show musl, not glibc +``` + +--- + +## πŸ“š Resources + +| Resource | Description | +|----------|-------------| +| [Docker Docs](https://docs.docker.com) | Docker documentation | +| [Playwright](https://playwright.dev) | E2E testing framework | +| [Compose File](docker-compose.yml) | Docker Compose configuration | +| [Rook Architecture](../docs/rook/architecture.md) | Backend internals | --- -## Config files reference +## πŸ“„ License -| File | Used by | DB | Notes | -|------|---------|----|-------| -| `test-configs/rook-dev.toml` | Path 1 (smoke test) | `:memory:` | No auth, no CRUD | -| `test-configs/rook-api-keys-test.toml` | Path 2 (Playwright E2E) | `/tmp/rook-e2e.db` | Auth enabled, CRUD enabled, cache disabled | -| `test-configs/rook-minimal.toml` | Manual / custom | configurable | Base for experiments | +MIT License - same as [Cortex repository](https://github.com/dallay/cortex). --- -## Dockerfile reference +
+ +**Docker** Β· **Playwright** Β· **Linux** Β· **macOS** -| File | Build type | Dashboard | Used by | -|------|-----------|-----------|---------| -| `dev/Dockerfile.dev` | debug | βœ— | Path 1 (smoke test, `just dev-*`) | -| `Dockerfile.dev` (repo root) | release | βœ“ | Path 2 (Playwright E2E) | -| `dev/Dockerfile.ubuntu` | release | βœ“ | Path 3 (multi-distro, ubuntu) | -| `dev/Dockerfile.alpine` | release | βœ“ | Path 3 (multi-distro, alpine) | +
diff --git a/docs/huginn/README.md b/docs/huginn/README.md index 19e5ac59..6c228c7e 100644 --- a/docs/huginn/README.md +++ b/docs/huginn/README.md @@ -1,174 +1,461 @@ -# Huginn +
-Huginn is the local Rust coding assistant and a product alongside Rook. The -service kernel, OpenAI-compatible streaming adapter, native tools, SQLite -sessions, scoped `AGENTS.md` context, compaction and trusted MCP stdio -client are implemented. Public distribution remains outside this MVP. +# πŸ€– Huginn -## Install and start +Local Rust coding assistant with native tools and MCP integration -Use the repository's Rust 1.89 toolchain on macOS or Linux: +[![Rust](https://img.shields.io/badge/rust-1.89%2B-DEA584?logo=rust)](https://www.rust-lang.org) +[![SQLite](https://img.shields.io/badge/sqlite-3-003B57?logo=sqlite)](https://www.sqlite.org) +[![MCP](https://img.shields.io/badge/MCP-ready-7C3AED?logo=modelcontextprotocol)](https://modelcontextprotocol.io) +[![License](https://img.shields.io/github/license/dallay/cortex)](https://github.com/dallay/cortex/blob/main/LICENSE) + +**Your local AI coding partner** β€” runs locally with access to your codebase. + +[Huginn Architecture](#-architecture) Β· [Installation](#-installation) Β· [Usage](#-usage) Β· [TUI Guide](#-tui-guide) Β· [Providers](providers-ui.md) + +
+ +--- + +## 🎯 What is Huginn? + +Huginn is a **local coding agent** built in Rust that works with your codebase. Unlike cloud-based AI assistants, Huginn runs entirely on your machine. + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Huginn: Local-First AI β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Your Machine Cloud Providers β”‚ β”‚ +β”‚ β”‚ ──────────── ─────────────── β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ Huginn β”‚ ─── API ───────▢ β”‚ OpenAI β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ (Local) β”‚ β”‚ Anthropic β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Local Tools β”‚ β”‚ +β”‚ β”‚ β–Ό β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ Your Code β”‚ ◀── Read/Write/Execute β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ πŸ”’ Code stays local β€” prompts and context sent to providers β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Key Principles + +| Principle | Description | +|-----------|-------------| +| πŸ”’ **Privacy-first** | Code stays local, only model requests go to cloud | +| πŸ’» **Native tools** | File ops, terminal, git β€” all built-in | +| πŸ”Œ **Extensible** | MCP stdio client for custom tools | +| πŸ“ **Scoped context** | `AGENTS.md` controls what Huginn sees | +| πŸ’Ύ **Session memory** | SQLite-backed conversation history | + +--- + +## ✨ Features + +| Feature | Description | +|---------|-------------| +| πŸ–₯️ **Ratatui TUI** | Beautiful terminal interface with colors and layout | +| πŸ”§ **Native tools** | File read/write, terminal execution, git operations | +| πŸ”Œ **MCP integration** | Connect to any MCP stdio server | +| πŸ’Ύ **SQLite sessions** | Persistent conversation history | +| πŸ“‹ **Scoped context** | Per-repo `AGENTS.md` for agent instructions | +| 🎯 **Tool calling** | Automatic tool selection based on task | +| πŸ“€ **JSON mode** | Machine-readable output for automation | +| 🌐 **Provider agnostic** | OpenAI-compatible API support | + +--- + +## πŸ—οΈ Architecture + +``` +huginn/ +β”‚ +β”œβ”€β”€ src/ +β”‚ β”œβ”€β”€ main.rs # Entry point, CLI parsing +β”‚ β”‚ +β”‚ β”œβ”€β”€ cli/ # Command handlers +β”‚ β”‚ β”œβ”€β”€ chat.rs # Interactive chat mode +β”‚ β”‚ β”œβ”€β”€ run.rs # Single command mode +β”‚ β”‚ └── sessions.rs # Session management +β”‚ β”‚ +β”‚ └── runtime/ +β”‚ β”œβ”€β”€ mod.rs # Core runtime +β”‚ β”œβ”€β”€ provider.rs # LLM provider abstraction +β”‚ β”œβ”€β”€ tools/ # Native tools +β”‚ β”‚ β”œβ”€β”€ file.rs # File operations +β”‚ β”‚ β”œβ”€β”€ terminal.rs # Shell commands +β”‚ β”‚ β”œβ”€β”€ git.rs # Git operations +β”‚ β”‚ └── mod.rs # Tool registry +β”‚ β”‚ +β”‚ β”œβ”€β”€ mcp/ # MCP client +β”‚ β”‚ β”œβ”€β”€ client.rs # Stdio client +β”‚ β”‚ └── protocol.rs # MCP protocol +β”‚ β”‚ +β”‚ β”œβ”€β”€ session.rs # SQLite session storage +β”‚ β”œβ”€β”€ context.rs # Context building +β”‚ └── ui/ # Ratatui UI components +β”‚ +β”œβ”€β”€ runtime/ # Huginn runtime crate (shared) +β”‚ β”œβ”€β”€ src/ +β”‚ β”‚ β”œβ”€β”€ service_kernel.rs +β”‚ β”‚ β”œβ”€β”€ streaming_adapter.rs # OpenAI-compatible streaming +β”‚ β”‚ β”œβ”€β”€ tools.rs +β”‚ β”‚ └── sessions.rs +β”‚ β”‚ +β”‚ └── tests/ +β”‚ └── fixtures/ +β”‚ +└── AGENTS.md # Per-repo agent instructions +``` + +### Runtime Flow + +``` +User Input + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Parser β”‚ ──▢ β”‚ Provider β”‚ ──▢ β”‚ Response β”‚ +β”‚ (Command) β”‚ β”‚ (LLM Call) β”‚ β”‚ (Streaming)β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Tool Call β”‚ + β”‚ Execution β”‚ + β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β–Ό β–Ό β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ File System β”‚ β”‚ Terminal β”‚ β”‚ Git β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## πŸš€ Installation + +### From Source ```bash +# Clone the repository +git clone https://github.com/dallay/cortex.git +cd cortex + +# Install globally cargo install --path apps/huginn --locked -huginn --provider mock --workspace /path/to/repository run "list files" + +# Or build only +cargo build --release -p huginn ``` -From the checkout, use `just huginn-run` or `cargo run -p huginn --` followed -by the same arguments. `mock` is an offline diagnostic provider with a -read-only `list files` example; it does not perform real coding reasoning. +### Requirements -En la TUI, usa `/login`, `/providers`, `/model` y `/logout` para -[gestionar conexiones con formularios secretos del host](providers-ui.md), -sin editar configuraciΓ³n ni reiniciar. La verificaciΓ³n de esta UI usa dobles; -no acredita aceptaciΓ³n de proveedores reales ni onboarding. +| Requirement | Version | Notes | +|-------------|---------|-------| +| Rust | 1.89+ | MSRV may be higher | +| Cargo | latest | Included with Rust | +| SQLite | system | Usually pre-installed | -For a model, set `HUGINN_BASE_URL` (including `/v1`), `HUGINN_MODEL`, and -`HUGINN_API_KEY` in the invoking shell, then run: +### Verify Installation ```bash -huginn --workspace /path/to/repository chat -huginn --workspace /path/to/repository --json run "Explain the project" -huginn sessions -huginn resume SESSION_UUID -huginn resume SESSION_UUID --prompt "Continue the task" -``` - -Interactive `chat` (or no subcommand) uses the Ratatui TUI when attached to a -terminal. `--line-mode` selects the line-oriented recovery adapter; `--json` -emits machine-readable events instead. - -### Chat suggestions - -- Type `/` to open the active command catalog with descriptions. - Search accepts prefixes and gapped characters, for example `/exinfo`. -- Type `@` at a token start to search workspace filenames. - Paths with spaces are inserted as `@"docs/my guide.md"`. - The reference is **text only**: it never reads or attaches file contents. -- Use ↑/↓ to select, Tab to complete without running, and Esc to close. - Enter runs the selected command; for files and arguments it only completes. - A later Enter sends the draft. Alt/Shift+Enter and Ctrl+J insert a newline. -- Plugins can declare descriptions, argument values, and paths through - `CommandMetadata` and `Contributions::register_command`. Existing commands - without metadata keep working; undeclared arguments are never inferred. - Summary commands are suggested only with a configured model. -- The filename index is built in the background once per chat connection, - with a 20,000-entry walk limit. Restart the chat to refresh it. - It excludes `.git`, `target`, `node_modules`, `.pnpm-store`, `.cache`, and - symbolic links; it does not interpret `.gitignore`. It reports a partial - index or failure. It is not a security boundary against concurrent - filesystem changes. -- Approvals and dialogs take priority over suggestions. Completing text - never grants permissions; a revoked plugin selection never runs its replacement. - -`doctor` valida configuraciΓ³n y muestra servicios sin contactar al modelo ni -iniciar MCP. Sin configuraciΓ³n explΓ­cita ni selecciΓ³n persistida utilizable, -informa `model_readiness: "unconfigured"`. Una selecciΓ³n recuperada solo indica -preparaciΓ³n local: no verifica disponibilidad remota. `run` y `resume --prompt` -necesitan un modelo y las credenciales que requiera el proveedor. `--db` elige -otra base de sesiones; `--config` elige un archivo TOML. - -## Configuration and permissions - -See [config.example.toml](../../apps/huginn/config.example.toml) for every -setting. The default location follows the OS configuration directory: on -macOS, `~/Library/Application Support/cortex/huginn/config.toml`; on Linux, -`~/.config/cortex/huginn/config.toml` (or the XDG override). If a new -install runs on a host that only has the legacy -`~/.../cortex/agent/config.toml`, Huginn reads it once (read-only) and -prints a warning suggesting the migration; it never overwrites the legacy -file. CLI options override the file; environment variables provide -defaults for the endpoint and model. API keys are loaded from a named -environment variable. Set `api_key_env = ""` for a local endpoint -without authentication. - -HTTPS endpoints use validated certificates. Plain HTTP requires -`allow_loopback_http = true` and a literal loopback IP (`127.0.0.1` or `[::1]`); -private/LAN addresses and DNS names are not a local exception. Existing local -HTTP configurations must explicitly enable this setting. Redirects are rejected. -Para los adaptadores integrados y los modelos Ollama probados anteriormente, -consulta [adaptadores y verificaciΓ³n local](inference-adapters.md). El -catΓ‘logo remoto no se consulta desde los formularios: la UI admite un modelo -candidato cuando no hay modelos estΓ‘ticos. La aceptaciΓ³n automatizada del flujo -completo con adaptadores reales sigue siendo una entrega de integraciΓ³n separada. - -Reads are limited to resolved paths within the workspace. Edits show their -complete diff and require approval; changed files require a new diff. -Shell and every MCP call require approval too. Ctrl+C interrupts a turn; -`/quit` ends a conversation. MCP startup asks separately. Only configured -environment variables are passed to MCP processes; native shell inherits -PATH only. Shell and MCP have full host access under the user's account -and must be trusted. - -One-shot mode denies effects unless explicitly granted for that invocation: +huginn --version +``` + +--- + +## πŸ“– Usage + +### Quick Start ```bash -huginn --allow native.edit_file,native.shell run "Fix the bug and run its tests" -``` - -Grants match exact action names, have no wildcard, and authorize all -occurrences of that action during this invocation. Available native -effects are `native.write_file`, `native.edit_file`, and `native.shell`. -MCP actions use `mcp.SERVER.start` and `mcp.SERVER.REMOTE_TOOL`. Grants -are never restored from a session. `--json` emits one typed event per -stdout line; diagnostics use stderr. - -### Environment variable fallback - -`AGENT_BASE_URL`, `AGENT_MODEL`, and `AGENT_API_KEY` are still read as a -fallback when the canonical `HUGINN_*` variables are unset. The fallback -exists so users who already exported the old names keep working after -the rename; new installations should set the `HUGINN_*` variables -directly. - -## Durable context and recovery - -Sessions store messages, calls, results, approval events and interruption -state in SQLite. Originals survive compaction. New databases use schema -version 1; newer unknown versions fail explicitly. One process may hold -a session at a time. Provider credentials are not stored. Repository -content, prompts and tool output are part of history and may themselves -contain sensitive text. - -Interrupted calls receive a result indicating unknown completion when -resumed; they are never automatically replayed. Inspect external effects -before requesting a replacement action. Compaction keeps the last two user -turns and complete tool pairs, summarizes older messages with the same -provider, and stops if it fails. Context accounting uses conservative -serialized bytes rather than a model tokenizer. - -Root and nested AGENTS.md documents are loaded with directory scope -labels on each iteration. Symlinks must resolve inside the workspace; -generated/dependency folders are excluded. Instructions are context and -cannot grant permissions. - -## Cross-process session locking - -Huginn acquires an advisory lock file before mutating a session. The lock filename remains `cortex-agent-session-.lock` during the -compatibility window. Both old and new executables acquire the same lock; -using separate names would allow two versions to mutate one SQLite session -at once. Huginn does not delete, copy or rewrite legacy SQLite databases -through a plain file copy. - -## Development and architecture - -- Code: [`apps/huginn`](../../apps/huginn/), [`core`](../../crates/huginn/core/), [`runtime`](../../crates/huginn/runtime/). -- [Implementation specification](implementation-specification.md) β€” contracts and limits. -- [Architecture decisions](adr/README.md) β€” accepted ADRs. -- [Implementation plan](implementation-plan.md) β€” milestones and acceptance boundaries. -- [Linux daily-use checklist](linux-daily-use.md) β€” manual acceptance workflow on Linux. -- [Validation record](validation.md) β€” automated and manual evidence; status of open items. -- `just huginn-test` runs deterministic kernel, coding, HTTP, MCP and CLI fixtures. -- `./scripts/huginn-linux-smoke.sh` verifies the local install on a Linux host without contacting a model. -- `just ci-local` runs the complete workspace gate, including Rook and Docker E2E. - -Huginn is independent of Rook's abstractions; Rook is not a supported backend -as of 2026-10-06 β€” see -[validation.md Β§ Rook compatibility result](validation.md#rook-compatibility-result). -Real-model validation and a Linux daily-use run must be recorded before -declaring the personal MVP fully accepted. MCP transport fixtures -require Python 3 at `/usr/bin/python3` on the supported platforms. - -Obsidian's rust-agent-harness-research remains the research source. The -repository is the canonical source of implementation specifications and -ADRs. +# 1. Set environment variables +export HUGINN_BASE_URL=https://api.openai.com/v1 +export HUGINN_MODEL=gpt-4o +export HUGINN_API_KEY=your-api-key + +# 2. Run in chat mode +huginn --workspace /path/to/your/project chat + +# 3. Or run a single command +huginn --workspace /path/to/your/project run "Explain this codebase" +``` + +### Command Reference + +| Command | Description | +|---------|-------------| +| `huginn chat` | Interactive TUI chat (default) | +| `huginn run ""` | Single command, exit | +| `huginn sessions` | List saved sessions | +| `huginn resume ` | Continue a session | +| `huginn --json run ""` | JSON output (for scripting) | + +### Environment Variables + +| Variable | Required | Description | +|----------|----------|-------------| +| `HUGINN_BASE_URL` | For non-mock providers | API endpoint (include `/v1`) | +| `HUGINN_MODEL` | For non-mock providers | Model name | +| `HUGINN_API_KEY` | For auth-required providers | API key (optional for mock/Ollama) | + +--- + +## πŸ–₯️ TUI Guide + +When you run `huginn chat`, you get a Ratatui-based terminal interface. + +### Layout + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Huginn - /path/to/workspace [?] [βš™] [βœ•] β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ πŸ€– Assistant β”‚ β”‚ +β”‚ β”‚ ───────────────── β”‚ β”‚ +β”‚ β”‚ Welcome to Huginn! Type / for commands. β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ πŸ‘€ You β”‚ β”‚ +β”‚ β”‚ ───────────────── β”‚ β”‚ +β”‚ β”‚ Explain the project structure β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ πŸ€– Assistant β”‚ β”‚ +β”‚ β”‚ ───────────────── β”‚ β”‚ +β”‚ β”‚ This is a Rust monorepo with... β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ > Explain the project structure [Send] β”‚ +β”‚ β”‚ +β”‚ Model: gpt-4o | Provider: OpenAI | Tokens: 1,234 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Commands (type `/` to open) + +| Command | Description | +|---------|-------------| +| `/login` | Configure provider credentials | +| `/providers` | Switch between providers | +| `/model` | Change the active model | +| `/logout` | Clear stored credentials | +| `/exinfo` | System information | +| `/clear` | Clear current conversation | +| `/quit` | Exit Huginn | + +### Keyboard Shortcuts + +| Shortcut | Action | +|----------|--------| +| `Ctrl+C` | Cancel current request | +| `Ctrl+L` | Clear screen | +| `Ctrl+Enter` | Send message | +| `↑/↓` | History navigation | + +--- + +## πŸ”§ Configuration + +### AGENTS.md + +Place an `AGENTS.md` file in your repository root to scope Huginn's context: + +```markdown +# Agent Instructions + +## Project Context +This is a Rust monorepo with Rook (AI proxy) and Huginn (coding agent). + +## Coding Standards +- Use 2-space indentation +- Run `cargo fmt` before commits +- Follow Rust idioms + +## Available Commands +- `just dev` - Start development +- `just test` - Run tests +- `just ci-local` - Full CI locally +``` + +### Provider Configuration + +Huginn supports OpenAI-compatible APIs: + +```bash +# OpenAI +export HUGINN_BASE_URL=https://api.openai.com/v1 +export HUGINN_MODEL=gpt-4o + +# Anthropic (via proxy) +export HUGINN_BASE_URL=http://localhost:3773/v1 +export HUGINN_MODEL=claude-3-sonnet-20240229 + +# Local Ollama +export HUGINN_BASE_URL=http://localhost:11434/v1 +export HUGINN_MODEL=llama3 +``` + +### Mock Provider (Offline Testing) + +```bash +# Test without real API calls +huginn --provider mock --workspace /path/to/repo run "list files" +``` + +The mock provider responds with predefined examples and does not perform real LLM calls. + +--- + +## πŸ”Œ MCP Integration + +Connect Huginn to MCP servers for extended capabilities via CLI configuration: + +```toml +# huginn.toml (or pass via --config) +[[mcp]] +name = "filesystem" +command = "npx" +args = ["-y", "@modelcontextprotocol/server-filesystem@0.6.3", "."] + +[[mcp]] +name = "git" +command = "npx" +args = ["-y", "@modelcontextprotocol/server-git@0.5.0"] +``` + +```bash +# From the Cortex repository root; "." allows filesystem access to this workspace +huginn --workspace . --config huginn.toml chat +``` + +> ⚠️ **Security Notice:** MCP servers run with your OS permissions and are not sandboxed. Only connect to servers you trust. + +### Available MCP Servers + +| Server | Version | Purpose | +|--------|---------|---------| +| `@modelcontextprotocol/server-filesystem` | 0.6.3 | File operations | +| `@modelcontextprotocol/server-git` | 0.5.0 | Git operations | +| `@modelcontextprotocol/server-brave` | latest | Web search | +| `@modelcontextprotocol/server-slack` | latest | Slack integration | + +--- + +## πŸ“ Examples + +### Explain Code + +```bash +huginn --workspace ./my-project run "Explain the main.rs entry point" +``` + +### Refactor Code + +```bash +huginn --workspace ./my-project run "Refactor the auth module to use async/await" +``` + +### Write Tests + +```bash +huginn --workspace ./my-project run "Write unit tests for the UserService" +``` + +### Generate Documentation + +```bash +huginn --workspace ./my-project run "Add doc comments to the public API" +``` + +### Git Operations + +```bash +huginn --workspace ./my-project run "Create a commit for the new feature with good message" +``` + +### JSON Output (CI/CD) + +```bash +huginn --workspace ./my-project --json run "Analyze the code and return metrics" +``` + +--- + +## πŸ§ͺ Testing + +```bash +# Run all tests +cargo test -p huginn + +# With coverage +cargo tarpaulin -p huginn +``` + +--- + +## πŸ”’ Security + +| Concern | Mitigation | +|---------|------------| +| API keys | Use environment variables, not config files | +| File access | Workspace-scoped β€” Huginn only accesses specified directory | +| Shell execution | Terminal commands require explicit approval | +| MCP tools | MCP calls require explicit approval | +| Session data | SQLite DB stored locally (no built-in encryption) | + +### Best Practices + +1. **Never commit API keys** β€” use environment variables +2. **Review tool calls** β€” Huginn shows what it will execute +3. **Scope workspaces** β€” Use `--workspace` to limit access +4. **Audit sessions** β€” Check `huginn sessions` for history + +--- + +## πŸ“š Resources + +| Resource | Description | +|---------|-------------| +| [Architecture](adr/README.md) | Design decisions and ADRs | +| [Providers UI](providers-ui.md) | Provider configuration in TUI | +| [Rook](../rook/README.md) | Companion AI proxy | +| [Cortex](../README.md) | Full project documentation | + +--- + +## πŸ“„ License + +MIT License - same as [Cortex repository](https://github.com/dallay/cortex). + +--- + +## πŸ™ Acknowledgments + +- Built with [Ratatui](https://ratatui.rs/) for the TUI +- Inspired by [Claude](https://claude.ai/) and [Cursor](https://cursor.sh/) +- MCP protocol by [Model Context Protocol](https://modelcontextprotocol.io) + +--- + +
+ +**Rust** Β· **Privacy-first** Β· **Local-first** Β· **MCP-native** + +