# OpenCode + LiteLLM Testing Guide (Nextcloud VM) **VM**: next (Nextcloud) @ 192.168.88.62 **OpenCode**: Running in Docker **API Gateway**: LiteLLM @ 192.168.88.27:4000 **Config Source**: Gitea @ 192.168.88.200:3000 --- ## ๐Ÿงช Test 1: Verify Configuration Loaded ### 1.1 Check Config File on VM ```bash ssh jgitta@192.168.88.62 # Check if config exists cat ~/.opencode/config.json | jq '.' # Expected output: { "apiProvider": "openai", "apiBase": "http://192.168.88.27:4000", "apiKey": "litellm-local-key-change-in-production", "model": "gpt-4o", "timeout": 600, "maxTokens": 4096, "verbose": true } ``` โœ… **If you see this config**: The setup is working! Config was pulled from Gitea. โŒ **If file doesn't exist**: Check docker logs (see troubleshooting below) ### 1.2 Check Docker Container Logs ```bash ssh jgitta@192.168.88.62 cd /path/to/docker-compose # View startup logs docker-compose logs opencode | tail -30 # Look for these messages: # โœ… ๐Ÿ”„ Fetching configuration from Gitea... # โœ… โœ… Configuration fetched successfully # โœ… โœ… OpenCode config loaded from Gitea # โœ… ๐Ÿš€ Starting OpenCode... ``` --- ## ๐ŸŒ Test 2: Verify Network Access ### 2.1 Can OpenCode Reach LiteLLM? ```bash ssh jgitta@192.168.88.62 # Test from inside the container docker exec opencode curl -s http://192.168.88.27:4000/models \ -H "Authorization: Bearer litellm-local-key-change-in-production" | jq '.data | length' # Expected output: 16 ``` โœ… **If you see 16**: OpenCode can reach the LiteLLM gateway! โŒ **If connection refused**: Check network/firewall ### 2.2 Can OpenCode Reach Gitea? ```bash docker exec opencode curl -s http://192.168.88.200:3000/api/v1/version | jq '.version' # Expected output: "1.21.4" ``` โœ… **If version shown**: Gitea is reachable โŒ **If connection refused**: Check Gitea status --- ## ๐Ÿ’ป Test 3: Test OpenCode API Calls ### 3.1 Direct API Test (Using gpt-4o) ```bash ssh jgitta@192.168.88.62 # Make a test API call through the LiteLLM gateway curl -X POST http://192.168.88.27:4000/chat/completions \ -H "Authorization: Bearer litellm-local-key-change-in-production" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o", "messages": [{"role": "user", "content": "What is 2+2?"}] }' 2>/dev/null | jq '.choices[0].message.content' ``` โš ๏ธ **With placeholder keys** (current setup): ``` OpenAIException - Error code: 401 - Incorrect API key ``` โœ… **This is EXPECTED** - proves the system is routing correctly! Once you add real API keys, you'll get actual responses. --- ## ๐ŸŽฏ Test 4: OpenCode Usage ### 4.1 Access OpenCode Web Interface If OpenCode has a web UI, access it: ``` http://192.168.88.62:8000 ``` (Port may differ - check your docker-compose) ### 4.2 Use OpenCode Command Line ```bash ssh jgitta@192.168.88.62 # OpenCode will use the config from ~/.opencode/config.json # pointing to LiteLLM at 192.168.88.27:4000 # Go to a project directory cd ~/my-project # Run OpenCode (it will use LiteLLM automatically) opencode # Or in background opencode & ``` ### 4.3 Test OpenCode with Code Files ```bash ssh jgitta@192.168.88.62 # Create a test project mkdir -p ~/opencode-test cd ~/opencode-test # Create a simple Python file cat > hello.py << 'EOF' def greet(name): """Greet someone by name""" # TODO: Add more greeting logic return f"Hello, {name}!" # Usage result = greet("World") print(result) EOF # Run OpenCode on this directory # It will use the LiteLLM gateway for any AI features opencode ``` --- ## ๐Ÿ” Test 5: Verify Config Updates Work ### 5.1 Change Model in Gitea On your workstation: ```bash # Clone the homelab-configs repo git clone http://192.168.88.200:3000/jgitta/homelab-configs.git cd homelab-configs # Edit the config to use Claude instead nano opencode/config.json # Change line: # FROM: "model": "gpt-4o", # TO: "model": "claude-3.5-sonnet", git add opencode/config.json git commit -m "Test: Switch to claude-3.5-sonnet" git push origin main ``` ### 5.2 Verify VM Pulls New Config ```bash ssh jgitta@192.168.88.62 # Restart OpenCode to pull latest cd /path/to/docker-compose docker-compose restart opencode # Wait 10 seconds sleep 10 # Check the config was updated cat ~/.opencode/config.json | jq '.model' # Should now show: "claude-3.5-sonnet" ``` โœ… **If model changed**: Config updates are working! --- ## ๐Ÿ“Š Complete Testing Checklist ```bash # Run all tests in sequence ssh jgitta@192.168.88.62 echo "Test 1: Config File" cat ~/.opencode/config.json | jq '.apiBase' # Expected: "http://192.168.88.27:4000" echo "" echo "Test 2: Docker Logs" docker-compose logs opencode | grep "โœ…" # Expected: Multiple โœ… messages echo "" echo "Test 3: LiteLLM Reachability" docker exec opencode curl -s http://192.168.88.27:4000/models \ -H "Authorization: Bearer litellm-local-key-change-in-production" | jq '.data | length' # Expected: 16 echo "" echo "Test 4: Gitea Reachability" docker exec opencode curl -s http://192.168.88.200:3000/api/v1/version | jq '.version' # Expected: "1.21.4" echo "" echo "Test 5: API Call (will fail with placeholder keys)" curl -X POST http://192.168.88.27:4000/chat/completions \ -H "Authorization: Bearer litellm-local-key-change-in-production" \ -H "Content-Type: application/json" \ -d '{"model": "gpt-4o", "messages": [{"role": "user", "content": "test"}]}' 2>/dev/null | jq '.detail | contains("401")' # Expected: true (authorization error with placeholder keys is OK) echo "" echo "โœ… All tests completed!" ``` --- ## ๐Ÿšจ Troubleshooting ### Problem: "Config file not found" ```bash # The docker-compose might not have pulled from Gitea docker-compose logs opencode | grep -i "fetch\|clone" # Check if Gitea is accessible curl http://192.168.88.200:3000/ # If fails, Gitea might be down # Manually update the config docker exec opencode mkdir -p /root/.opencode docker exec opencode cat > /root/.opencode/config.json << 'EOF' { "apiProvider": "openai", "apiBase": "http://192.168.88.27:4000", "apiKey": "litellm-local-key-change-in-production", "model": "gpt-4o" } EOF ``` ### Problem: "Connection refused" to LiteLLM ```bash # Check if LiteLLM is running on docker-server curl http://192.168.88.27:4000/models # Check docker-server networking ssh root@192.168.88.27 docker ps | grep litellm docker logs litellm | tail -20 # Restart if needed cd /opt/litellm docker-compose restart ``` ### Problem: "Config not updating after git push" ```bash # Containers only pull on startup # Restart OpenCode to fetch latest docker-compose restart opencode # Or fully recreate docker-compose down docker-compose up -d opencode ``` ### Problem: "OpenCode not starting" ```bash # Check full error logs docker-compose logs opencode # Check if git/curl are available in container docker exec opencode which git docker exec opencode which curl # If missing, update the docker image or Dockerfile ``` --- ## ๐ŸŽ“ Next Steps 1. **Verify all 5 tests pass** โœ… 2. **Add real API keys** to `/opt/litellm/.env` on docker-server 3. **Test actual API calls** without 401 errors 4. **Use OpenCode normally** - it will route through LiteLLM automatically 5. **Manage configs centrally** via Gitea - no per-VM setup needed --- ## ๐Ÿ“ Key Points - โœ… OpenCode pulls config from Gitea at startup - โœ… Config points to LiteLLM gateway at 192.168.88.27:4000 - โœ… All 16 models available through LiteLLM - โœ… Change model for all VMs by editing one file in Gitea - โœ… No per-VM configuration needed - โœ… Network is internal only (no internet exposure) --- ## ๐Ÿ”— Related Documentation - **LiteLLM Setup**: `litellm-complete-setup.md` - **Models Available**: `litellm-models-update.md` - **Implementation Guide**: `gitea-centralized-implementation.md`