# ๐Ÿš€ AI Dev Factory - Session Continuation Guide **Last Updated:** 2025-12-01 **Current Phase:** Phase 2 - OpenHands Integration (SDK Mode) โœ… COMPLETED **Time to Completion:** โœ… All tasks completed **Current Approach:** OpenHands SDK via SSH wrapper โœ… --- ## ๐Ÿ“Š CURRENT STATUS ### โœ… What's Working: - **Gitea:** https://git.oky.sh (HTTPS, PostgreSQL backend) - **n8n:** https://n8n.oky.sh (HTTPS, workflow automation) - **Caddy:** Auto SSL with Let's Encrypt - **SSH:** n8n โ†’ localhost credentials configured and working - **OpenHands CLI:** `/home/bam/.local/bin/openhands` (v1.3.0) - **OpenHands SDK Wrapper:** `/home/bam/openhands-sdk-wrapper-sh.sh` (sh-compatible) - **Working n8n Workflow:** "OpenHands SDK Clean Working" (ID: 9cgyx4hHEvGjyEaE) ### โœ… Completed: - **SSH Authentication Fixed** - Directory permissions corrected - **n8n Workflow Created** - Successfully executes OpenHands SDK tasks - **File Verification Working** - Workflow confirms file creation - **Clean Workflow Structure** - Editable in n8n UI without errors - **Workflow Cleanup Completed** - Deleted 20 test workflows, kept only working one - **Temporary Files Cleaned** - Removed all test files and unnecessary scripts - **Database Updated** - Only "OpenHands SDK Clean Working" remains (ID: 9cgyx4hHEvGjyEaE) ### ๐ŸŽฏ Goal: Create automated workflow: Gitea push โ†’ n8n โ†’ OpenHands SDK (via SSH) โ†’ Build/Test --- ## ๐Ÿ”ง SYSTEM CONFIGURATION ### VM Details: ``` Hostname: ai-dev-node IP: 10.10.10.11 User: bam CPU: 8 vCPU RAM: 24GB (optimized from 40GB) OS: Ubuntu 22.04 ``` ### Services Running: ```bash docker compose ps # Expected output: # - caddy (ports 80, 443) # - gitea (port 3333 internal, 2229 SSH) # - n8n (port 5678 internal) # - postgres (port 5432 internal) ``` ### Important Directories: ``` /home/bam/services-stack/ # Docker services (Gitea, n8n, Caddy) /home/bam/.local/bin/ # OpenHands CLI /home/bam/.openhands/ # OpenHands config & sessions โ”œโ”€โ”€ agent_settings.json # Agent configuration โ”œโ”€โ”€ cache/ # Model cache โ”œโ”€โ”€ conversations/ # Chat history โ”œโ”€โ”€ sessions/ # Active sessions data โ””โ”€โ”€ settings.json # LLM & server settings /home/bam/workspace/ # Default workspace for builds /home/bam/.ssh/n8n_key # SSH key for n8n automation ``` ### API Keys Location: ``` /home/bam/openhands/.env # Contains: # MINIMAX_API_KEY=xxx (Primary LLM) # DEEPSEEK_API_KEY=xxx (Backup LLM) # OPENAI_API_KEY=xxx (Optional 2nd backup) ``` --- ## ๐ŸŽฏ NEXT STEPS: Gitea Webhook Integration with OpenHands SDK ### Step 1: Create Gitea Webhook (10 min) **Goal:** Trigger n8n workflow on git push events **In Gitea (https://git.oky.sh):** 1. Go to repository Settings โ†’ Webhooks โ†’ Add Webhook โ†’ Gitea 2. Configure: ``` Target URL: https://n8n.oky.sh/webhook/gitea-push HTTP Method: POST Content Type: application/json Secret: [generate random string] Trigger On: Push events Active: โœ“ ``` 3. Save and test the webhook ### Step 2: Create Webhook-Triggered n8n Workflow (30 min) **Goal:** Replace manual trigger with webhook that calls OpenHands SDK **Workflow Design:** ``` [1] Webhook Trigger (Gitea push) โ†“ [2] Extract repo info (JSON parser) โ†“ [3] SSH - Clone/Update Repository โ†“ [4] SSH - Execute OpenHands SDK (Wrapper) โ†’ Task: "Build and test project {{ $json.repository.name }}" โ†“ [5] SSH - Verify Build Success โ†’ Check for build artifacts โ†“ [6] HTTP - Update Gitea Commit Status โ†’ POST to Gitea API with success/failure ``` --- ### Step 1.5: Configure Backup LLM Models (10 min) **Goal:** Setup DeepSeek V2 as fallback when MiniMax fails OpenHands can use multiple LLM providers with automatic fallback. **Check current config:** ```bash cat /home/bam/.openhands/settings.json ``` **Update settings to include backup models:** ```bash nano /home/bam/.openhands/settings.json ``` **Add LLM configuration:** ```json { "LLM_MODEL": "openai/MiniMax-M2", "LLM_API_KEY": "${MINIMAX_API_KEY}", "LLM_BASE_URL": "https://api.minimax.io/v1", "LLM_FALLBACK_MODELS": [ { "model": "deepseek/deepseek-coder-v2", "api_key": "${DEEPSEEK_API_KEY}", "base_url": "https://api.deepseek.com/v1" }, { "model": "gpt-4o", "api_key": "${OPENAI_API_KEY}", "base_url": "https://api.openai.com/v1" } ], "LLM_TIMEOUT": 60, "LLM_RETRY_COUNT": 3 } ``` **Verify API keys are loaded:** ```bash cat /home/bam/openhands/.env # Should contain: # MINIMAX_API_KEY=xxx # DEEPSEEK_API_KEY=xxx # OPENAI_API_KEY=xxx (optional backup) ``` **Note:** Exact config format may vary. Check OpenHands documentation or existing settings.json structure. The systemd service will load these env vars automatically. **Restart OpenHands to apply:** ```bash sudo systemctl restart openhands.service sudo systemctl status openhands.service ``` --- ### Step 2: Discover API Endpoints (15 min) **Goal:** Find available API endpoints for triggering tasks **Check OpenHands documentation:** ```bash # Look for API docs in help /home/bam/.local/bin/openhands serve --help # Or check if web UI exposes API docs: # Visit: http://10.10.10.11:3000/docs # Or: http://10.10.10.11:3000/api/docs ``` **Expected endpoints (typical OpenHands API):** ``` POST /api/sessions # Create new session POST /api/sessions/{id}/messages # Send task message GET /api/sessions/{id} # Get session status GET /api/sessions/{id}/events # Get execution events ``` **Test manually:** ```bash # Create session curl -X POST http://localhost:3000/api/sessions \ -H "Content-Type: application/json" \ -d '{ "workspace": "/home/bam/workspace", "model": "openai/MiniMax-M2", "api_key": "your_minimax_key" }' # Response should include session_id ``` **If API endpoints unclear:** - Check OpenHands GitHub docs - Inspect network requests in web UI (browser DevTools) - Look for OpenAPI/Swagger spec --- ### Step 3: Create n8n โ†’ OpenHands API Workflow (45 min) **Goal:** Build n8n workflow that calls OpenHands API #### Workflow Design: ``` [1] Manual Trigger (for testing) โ†“ [2] HTTP Request - Create Session โ†’ POST /api/sessions โ†’ Save session_id โ†“ [3] HTTP Request - Send Task โ†’ POST /api/sessions/{session_id}/messages โ†’ Body: { "task": "Create file test.txt" } โ†“ [4] Wait 5 seconds โ†“ [5] HTTP Request - Get Status (loop until done) โ†’ GET /api/sessions/{session_id} โ†’ Check if "status": "completed" โ†“ [6] If Node - Check Success โ”œโ”€ TRUE โ†’ [7] Get Results โ””โ”€ FALSE โ†’ [8] Error Handler ``` #### n8n Configuration: **Node 1: Manual Trigger** - Just add it, no config **Node 2: HTTP Request - Create Session** ``` Method: POST URL: http://127.0.0.1:3000/api/sessions Headers: Content-Type: application/json Body: { "workspace": "/home/bam/workspace", "model": "openai/MiniMax-M2", "api_key": "{{$env.MINIMAX_API_KEY}}" } Options: Response Format: JSON ``` **Node 3: HTTP Request - Send Task** ``` Method: POST URL: http://127.0.0.1:3000/api/sessions/{{ $json.session_id }}/messages Body: { "task": "Create a file named test.txt with content: Hello from n8n API!" } ``` **Node 4: Wait Node** ``` Time: 5 seconds ``` **Node 5: HTTP Request - Get Status** ``` Method: GET URL: http://127.0.0.1:3000/api/sessions/{{ $node["HTTP Request"].json.session_id }} # May need to loop this until status is "completed" # Use n8n Loop node if available ``` **Node 6: SSH - Verify File Created** ``` Credentials: ai-dev-localhost Command: cat /home/bam/workspace/test.txt ``` #### Test Workflow: 1. Execute manually 2. Check each node output 3. Verify file created in /home/bam/workspace/ --- ### Step 4: Gitea Webhook Integration (30 min) **Goal:** Trigger n8n workflow on git push #### In Gitea (https://git.oky.sh): 1. Create test repository: `test-project` 2. Go to Settings โ†’ Webhooks โ†’ Add Webhook โ†’ Gitea 3. Configure: ``` Target URL: https://n8n.oky.sh/webhook/gitea-push HTTP Method: POST Content Type: application/json Secret: [generate random string] Trigger On: Push events Active: โœ“ ``` 4. Test webhook #### In n8n: 1. Replace Manual Trigger with Webhook Trigger 2. Configure: ``` Webhook URLs: Production: https://n8n.oky.sh/webhook/gitea-push HTTP Method: POST Authentication: Header Auth Name: X-Gitea-Signature Value: [your secret from Gitea] Response: Mode: Last Node Code: 200 ``` 3. Extract data: ``` Repository: {{ $json.repository.full_name }} Commit: {{ $json.commits[0].message }} Branch: {{ $json.ref }} ``` 4. Pass to OpenHands: ``` Task: "Build and test project {{ $json.repository.full_name }} on commit {{ $json.after }}" Workspace: "/home/bam/workspace/{{ $json.repository.name }}" ``` #### Test: ```bash # In test-project repo echo "Test" > README.md git add . git commit -m "Test webhook" git push origin main # Check n8n workflow executes # Check OpenHands builds project ``` --- ### Step 5: Build Workflow with Retry Logic (1-2 hours) **Goal:** Production-ready workflow with error handling #### Enhanced Workflow: ``` [1] Webhook Trigger (Gitea push) โ†“ [2] Extract Repo Info โ†“ [3] Clone/Update Repository (SSH) โ†’ git clone or git pull โ†“ [4] Create OpenHands Session โ†“ [5] Send Build Task โ†’ Task: "Run npm install, npm test, npm build" โ†“ [6] Poll Status (Loop) โ†’ Check every 10s โ†’ Timeout: 5 minutes โ†“ [7] If Node - Build Success? โ”œโ”€ YES โ†’ [8] Success Notification โ”‚ โ””โ”€ Update commit status โœ… โ”‚ โ””โ”€ NO โ†’ [9] Get Error Details โ†“ [10] Send Feedback to OpenHands โ†’ "Build failed with: {error}, please fix" โ†“ [11] Retry Counter (max 3) โ”œโ”€ < 3 โ†’ Back to [5] โ””โ”€ โ‰ฅ 3 โ†’ [12] Final Failure Notification ``` #### Key Components: **Clone Repository Node (SSH):** ```bash cd /home/bam/workspace if [ -d "{{ $json.repo_name }}" ]; then cd {{ $json.repo_name }} && git pull else git clone {{ $json.clone_url }} fi ``` **Build Task (to OpenHands):** ```json { "task": "Navigate to /home/bam/workspace/{{ $json.repo_name }} and run: npm install && npm test && npm build. Report any errors.", "workspace": "/home/bam/workspace/{{ $json.repo_name }}", "max_iterations": 20 } ``` **Retry Logic (n8n Function Node):** ```javascript // Get retry count from workflow static data const retries = $workflow.staticData.retry_count || 0; if (retries >= 3) { return { action: 'fail', message: 'Max retries exceeded' }; } // Increment retry $workflow.staticData.retry_count = retries + 1; return { action: 'retry', attempt: retries + 1, feedback: $json.error_message }; ``` **Success Notification (HTTP to Gitea API):** ``` POST https://git.oky.sh/api/v1/repos/{{ $json.repo }}/statuses/{{ $json.commit_sha }} Authorization: token YOUR_GITEA_TOKEN Body: { "state": "success", "description": "Build passed", "context": "openhands/build" } ``` --- ## ๐Ÿงช TESTING CHECKLIST ### Integration Tests: - [ ] OpenHands server starts and responds - [ ] API creates sessions successfully - [ ] API accepts and executes tasks - [ ] Tasks complete and return results - [ ] n8n can call all API endpoints - [ ] Webhook receives Gitea events - [ ] Repository clones correctly - [ ] Build task executes - [ ] Success path works end-to-end - [ ] Failure triggers retry - [ ] Max retries stops infinite loop - [ ] Notifications sent correctly ### Error Scenarios: - [ ] Invalid API request - [ ] OpenHands timeout - [ ] Build failure (syntax error) - [ ] Network issues - [ ] Git clone failure - [ ] Webhook auth failure --- ## ๐Ÿ“‹ TROUBLESHOOTING ### OpenHands Server Won't Start: ```bash # Check if port in use sudo netstat -tulpn | grep 3000 # Check OpenHands logs sudo journalctl -u openhands.service -n 50 # Try manual start to see errors /home/bam/.local/bin/openhands serve ``` ### API Endpoints Not Found: ```bash # Check OpenHands version /home/bam/.local/bin/openhands --version # May need to update pipx upgrade openhands-ai # Or reinstall pipx uninstall openhands-ai pipx install openhands-ai ``` ### n8n Cannot Reach OpenHands: ```bash # Test from n8n container docker exec -it n8n curl http://host.docker.internal:3000 # If fails, check if n8n has host.docker.internal access # May need to add to docker-compose: extra_hosts: - "host.docker.internal:host-gateway" ``` ### Webhook Not Triggering: ```bash # Check n8n webhook URL is accessible curl https://n8n.oky.sh/webhook/gitea-push # Check Gitea webhook logs: # Gitea UI โ†’ Repository โ†’ Settings โ†’ Webhooks โ†’ Recent Deliveries # Test with manual webhook trigger in Gitea UI ``` --- ## ๐ŸŽฏ SUCCESS CRITERIA **Phase 2 Complete When:** 1. โœ… OpenHands server running persistently 2. โœ… n8n can create sessions via API 3. โœ… Simple test task executes successfully 4. โœ… Gitea webhook triggers n8n workflow 5. โœ… End-to-end: Push โ†’ Build โ†’ Success/Fail **Phase 3 Complete When:** 1. โœ… Retry logic working (max 3 attempts) 2. โœ… Error feedback to OpenHands 3. โœ… Commit status updates in Gitea 4. โœ… Tested with real project build --- ## ๐Ÿ“š REFERENCE COMMANDS ### Quick Status Check: ```bash # All services status cd /home/bam/services-stack && docker compose ps # OpenHands server sudo systemctl status openhands.service # Check OpenHands API curl http://localhost:3000/ # n8n workflows curl -u admin:password https://n8n.oky.sh/api/v1/workflows ``` ### Restart Services: ```bash # Restart all Docker services cd /home/bam/services-stack docker compose restart # Restart OpenHands only sudo systemctl restart openhands.service # Restart n8n only docker compose restart n8n ``` ### View Logs: ```bash # OpenHands logs sudo journalctl -u openhands.service -f # n8n logs docker logs -f n8n # Caddy logs docker logs -f caddy # Gitea logs docker logs -f gitea ``` --- ## ๐Ÿ” CREDENTIALS REFERENCE ### n8n Login: - URL: https://n8n.oky.sh - User: admin (owner account) - Password: [set during setup] ### Gitea Login: - URL: https://git.oky.sh - User: [admin account] - Password: [set during setup] ### API Keys: - MiniMax: `/home/bam/openhands/.env` - SSH Key: `/home/bam/.ssh/n8n_key` --- ## โฑ๏ธ ESTIMATED TIME BREAKDOWN - Step 1: OpenHands Server Setup: **15 min** - Step 1.5: Backup LLM Configuration: **10 min** - Step 2: API Discovery: **15 min** - Step 3: n8n API Workflow: **45 min** - Step 4: Gitea Webhook: **30 min** - Step 5: Retry Logic: **1-2 hours** - Testing & Debugging: **30 min** **Total: 3-4 hours** --- ## ๐Ÿš€ READY TO START? **Pre-flight Checklist:** - [ ] All services running (docker compose ps) - [ ] Can access Gitea (https://git.oky.sh) - [ ] Can access n8n (https://n8n.oky.sh) - [ ] SSH to ai-dev-node working - [ ] Fresh terminal session **First Command:** ```bash /home/bam/.local/bin/openhands serve ``` If starts successfully โ†’ proceed to Step 1 systemd service! If error โ†’ investigate OpenHands CLI installation --- ## ๐Ÿ“ NOTES - **Port 3000:** OpenHands serve uses port 3000 (not configurable in CLI v1.3.0) - **Note:** This conflicts with Gitea's internal port 3000, but OK since Gitea exposed as 3333 - OpenHands API: http://localhost:3000 (localhost only) - n8n will access via http://host.docker.internal:3000 from container - **API Mode vs Headless:** API is more reliable for automation - **Persistence:** systemd service ensures OpenHands survives reboots - **Security:** OpenHands API on localhost only (127.0.0.1) - **Scaling:** Can add more OpenHands instances later - **LLM Fallback:** MiniMax M2 โ†’ DeepSeek V2 โ†’ OpenAI GPT-4o (if configured) **Good luck!** ๐ŸŽฏ