diff --git a/.cursor/rules/deployment.md b/.cursor/rules/deployment.md new file mode 100644 index 0000000..6f90542 --- /dev/null +++ b/.cursor/rules/deployment.md @@ -0,0 +1,152 @@ +# Open Agent - Deployment Guide + +## Production Server + +| Property | Value | +|----------|-------| +| **Host** | `95.216.112.253` | +| **SSH Access** | `ssh root@95.216.112.253` | +| **Backend URL** | `https://agent-backend.thomas.md` | +| **Dashboard URL** | `https://agent.thomas.md` (Vercel deployment) | +| **Environment file** | `/etc/open_agent/open_agent.env` | +| **Binary location** | `/usr/local/bin/open_agent` | +| **Systemd service** | `open_agent` | +| **Source code** | `/root/open_agent` | + +## Port Configuration + +| Service | Local Port | Production URL | +|---------|-----------|----------------| +| Backend API | 3000 | https://agent-backend.thomas.md | +| Dashboard | 3001 | https://agent.thomas.md | + +## Local Development + +- **Backend API**: `http://127.0.0.1:3000` (Rust server via `cargo run`) +- **Dashboard**: `http://127.0.0.1:3001` (Next.js via `bun run dev`) +- **Environment files**: + - Backend: `.env` in project root + - Dashboard: `dashboard/.env.local` + +## Common Operations + +### Check Service Status +```bash +ssh root@95.216.112.253 'systemctl status open_agent' +``` + +### View Logs +```bash +ssh root@95.216.112.253 'journalctl -u open_agent -f' +``` + +### Restart Service +```bash +ssh root@95.216.112.253 'systemctl restart open_agent' +``` + +### Edit Environment Variables +```bash +ssh root@95.216.112.253 'vim /etc/open_agent/open_agent.env' +# Then restart: +ssh root@95.216.112.253 'systemctl restart open_agent' +``` + +## Full Redeployment + +To redeploy from scratch: + +```bash +# 1. SSH into server +ssh root@95.216.112.253 + +# 2. Go to source directory +cd /root/open_agent + +# 3. Pull latest changes +git pull + +# 4. Build release binary +cargo build --release + +# 5. Copy binary to /usr/local/bin +cp target/release/open_agent /usr/local/bin/open_agent + +# 6. Restart service +systemctl restart open_agent + +# 7. Check status +systemctl status open_agent +``` + +## SSH Key for Git Access + +The VPS has a cursor SSH key at `~/.ssh/cursor` which has read access to private GitHub repositories. The git remote should be configured to use SSH: + +```bash +# Check remote URL +git remote -v + +# If needed, switch to SSH: +git remote set-url origin git@github.com:owner/open_agent.git +``` + +Make sure the SSH config uses the cursor key for github.com: + +```bash +# ~/.ssh/config on VPS +Host github.com + HostName github.com + User git + IdentityFile ~/.ssh/cursor +``` + +## Systemd Service Configuration + +The service file is typically at `/etc/systemd/system/open_agent.service`: + +```ini +[Unit] +Description=Open Agent +After=network.target + +[Service] +Type=simple +User=root +WorkingDirectory=/root/open_agent +EnvironmentFile=/etc/open_agent/open_agent.env +ExecStart=/usr/local/bin/open_agent +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +## Nginx Reverse Proxy + +The backend is proxied through nginx at `agent-backend.thomas.md`. The nginx config typically includes: + +```nginx +server { + server_name agent-backend.thomas.md; + + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + # SSL managed by certbot +} +``` + +## Security Notes + +- The API requires authentication when `DEV_MODE=false` +- JWT tokens are used for dashboard authentication +- Keep `.env` and `open_agent.env` out of version control +- The agent has full machine access - be careful with what tasks you submit diff --git a/.cursorrules b/.cursorrules deleted file mode 100644 index 395e984..0000000 --- a/.cursorrules +++ /dev/null @@ -1,178 +0,0 @@ -# Open Agent - Cursor Rules & Project Philosophy - -## Project Overview - -Open Agent is a minimal autonomous coding agent implemented in Rust. It is designed to be: -- **AI-maintainable**: Rust's strong type system and compiler provide immediate feedback -- **Self-contained**: No external dependencies beyond OpenRouter for LLM access -- **Full-access**: Has complete access to the local machine (filesystem, terminal, network) -- **Provable**: Code structured for future formal verification in Lean - -## Architecture (v2: Hierarchical Agent Tree) - -### Agent Hierarchy -``` - ┌─────────────┐ - │ RootAgent │ - └──────┬──────┘ - ┌─────────────────┼─────────────────┐ - ▼ ▼ ▼ - ┌───────────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ - │ Complexity │ │ Model │ │ Task │ │ Verifier │ - │ Estimator │ │ Selector │ │ Executor │ │ │ - └───────────────┘ └─────────────┘ └─────────────┘ └──────────┘ -``` - -### Agent Types - -| Type | Role | Children | -|------|------|----------| -| **RootAgent** | Top-level orchestrator, receives API tasks | All leaf types | -| **NodeAgent** | Intermediate orchestrator for subtasks | Executor, Verifier | -| **ComplexityEstimator** | Estimates task difficulty (0-1 score) | None (leaf) | -| **ModelSelector** | Picks optimal model (U-curve optimization) | None (leaf) | -| **TaskExecutor** | Executes tasks using tools | None (leaf) | -| **Verifier** | Validates completion (hybrid) | None (leaf) | - -### Task Flow -1. Receive task via HTTP API -2. **Estimate Complexity** (ComplexityEstimator) -3. If complex: **Split into subtasks** with budget allocation -4. **Select Model** for each (sub)task (U-curve cost optimization) -5. **Execute** using tools (TaskExecutor) -6. **Verify** completion (Verifier: programmatic → LLM fallback) -7. Aggregate results and return - -### U-Curve Model Selection -``` -Cost - ^ - | * * - | * * - | * * * - | * * * * - | * * - +-------------------------> Model Capability - (cheap/weak) (optimal) (expensive/strong) -``` -- Cheap models: low per-token cost, high failure rate, more retries -- Expensive models: high per-token cost, low failure rate -- **Optimal**: minimizes expected total cost - -## Module Structure - -``` -src/ -├── agents/ # Hierarchical agent system -│ ├── mod.rs # Agent traits (Agent, OrchestratorAgent, LeafAgent) -│ ├── types.rs # AgentId, AgentType, AgentResult, Complexity -│ ├── context.rs # Shared context for agent tree -│ ├── tree.rs # Tree structure management -│ ├── orchestrator/ # Orchestrator agents -│ │ ├── root.rs # RootAgent (top-level) -│ │ └── node.rs # NodeAgent (intermediate) -│ └── leaf/ # Leaf agents (specialized workers) -│ ├── complexity.rs # ComplexityEstimator -│ ├── model_select.rs # ModelSelector with U-curve -│ ├── executor.rs # TaskExecutor (tools in a loop) -│ └── verifier.rs # Hybrid verification -├── task/ # Task types with invariants -│ ├── task.rs # Task, TaskId, TaskStatus -│ ├── subtask.rs # Subtask, SubtaskPlan -│ └── verification.rs # VerificationCriteria, ProgrammaticCheck -├── budget/ # Cost tracking and pricing -│ ├── budget.rs # Budget with spend/allocate invariants -│ ├── pricing.rs # OpenRouter pricing client -│ └── allocation.rs # Budget allocation strategies -├── agent/ # Original simple agent (legacy) -├── api/ # HTTP interface -├── llm/ # LLM client (OpenRouter) -├── tools/ # Tool implementations -└── config.rs # Configuration -``` - -## Design for Provability - -### Conventions for Future Lean Proofs -1. **Pre/Postconditions**: Document as `/// Precondition:` and `/// Postcondition:` comments -2. **Invariants**: Document struct invariants, enforce in constructors -3. **Algebraic Types**: Use enums with exhaustive matching, no `_` catch-all -4. **Pure Functions**: Separate pure logic from IO where possible -5. **Result Types**: Never panic, always return `Result` - -### Example -```rust -/// Allocate budget for a subtask. -/// -/// # Precondition -/// `amount <= self.remaining_cents()` -/// -/// # Postcondition -/// `self.allocated_cents` increases by exactly `amount` -pub fn allocate(&mut self, amount: u64) -> Result<(), BudgetError> -``` - -## Adding a New Leaf Agent - -1. Create `src/agents/leaf/your_agent.rs` -2. Implement `Agent` trait: - - `id()`, `agent_type()`, `execute()` -3. Implement `LeafAgent` trait: - - `capability()` → add variant to `LeafCapability` enum -4. Register in `RootAgent::new()` or relevant orchestrator -5. Document pre/postconditions for provability - -## API Contract - -``` -POST /api/task - Submit task (uses hierarchical agent) -GET /api/task/{id} - Get task status and result -GET /api/task/{id}/stream - Stream progress via SSE -GET /api/health - Health check -``` - -## Environment Variables - -``` -OPENROUTER_API_KEY - Required. Your OpenRouter API key -DEFAULT_MODEL - Optional. Default: openai/gpt-4.1-mini -WORKSPACE_PATH - Optional. Default: current directory -HOST - Optional. Default: 127.0.0.1 -PORT - Optional. Default: 3000 -MAX_ITERATIONS - Optional. Default: 50 -``` - -## Deployment - -### Production Server -- **Host**: `95.216.112.253` -- **SSH Access**: `ssh root@95.216.112.253` (key-based auth available to agent) -- **Environment files**: Located in `/root/open_agent/.env` on the server - -### Local Development -- **Backend API**: `http://127.0.0.1:3000` (Rust server via `cargo run`) -- **Dashboard**: `http://127.0.0.1:3001` (Next.js via `bun run dev`) -- **Environment files**: - - Backend: `.env` in project root - - Dashboard: `dashboard/.env.local` - -## Security Considerations - -This agent has **full machine access**. It can: -- Read/write any file the process can access -- Execute any shell command -- Make network requests - -When deploying: -- Run as a limited user -- Use workspace isolation -- Consider a sandbox for terminal commands -- Never expose the API publicly without authentication - -## Future Work - -- [ ] Formal verification in Lean (extract pure logic) -- [ ] WebSocket for bidirectional streaming -- [ ] Semantic code search (embeddings-based) -- [x] Multi-model support (U-curve optimization) -- [x] Cost tracking (Budget system)